linux新核心的時鐘機制代碼讀後感

來源:互聯網
上載者:User

如果說cfs是linux的一個很有創意的機制的話,那麼linux中另一個創意就是nohz,我在前面已 經寫了好幾篇關於nohz的文章了,因此本文就不再闡述代碼細節了,linux的創意在於設計而不在代碼,代碼主要解決的問題是實用性,就像gcc一樣, 就是一個編譯器,應用編譯原理設計而出,它內部卻充實著編譯原理之外的巧妙。有血有肉才活得精彩,如果說nohz之前的linux核心是骨架的話,那麼從 nohz之後,linux開始了精彩,之後幾乎瞬時,cfs出現了,然後是cgroup...cgroup正式開始了虛擬容器,從此linux再也不用被 unix老大們看作是小孩子了,nohz標誌著linux開始成熟起來。nohz為何這麼重要呢?因為它直接關係到了效能,直接聯絡著系統的心跳,在之 前,系統總是被動的接受時鐘中斷,然後運行中斷處理常式最終可能導致調度的發生,如果實在沒有任務可以運行,那麼就執行idle,這也許也算一種創意,可 是時鐘中斷還是會周期性的打破idle,然後查詢有沒有需要做的事情,如果沒有繼續idle,這種方式沒有什麼問題,可是我們總是希望系統可以主動的做些 事情,比如不是被動的接受中斷而是主動的設定什麼時候中斷,因此必須將系統時鐘發生中斷這件事進行向上抽象,於是相應的clocksource和 clock_event_device,這兩個結構體就是時鐘以及時鐘行為的抽象,clocksource代表了一個時鐘源,一般都會有一個計數器,其中 的read回呼函數就是負責讀出其計數器的值,可是我們為何找不到write或者set之類的回呼函數呢?這些回呼函數其實不應該在 closksource中,而應該在clock_event_device中,實際上,clockevent只是一個鐘,你可以類比我們用的鐘 表,clocksource就是一個鐘錶,我們需要一個鐘錶就是需要讀出它的指標的值從而知道現在幾點,就是這些,因此鐘錶都會有顯示盤用於讀數,至於鐘 表怎麼運作,那就是鐘錶內部的機械原理了,記住,鐘錶就是用來讀數的,另外我們為了害怕誤事而需要鬧鈴,需要的是鬧鈴在一個時間段之後把我們喚醒,這是個 事情,而這個事情不一定非要有鐘錶,當然鐘錶的讀數會為我們提供有用的參考值,這樣的話鐘錶和鬧鈴就解耦合了,再重申一遍,不要因為有鬧鐘的存在就說鐘錶 都會響鈴或者說鬧鈴都有鐘錶,它們其實是兩個東西,鐘錶為你展示某些事情,而鬧鈴需要你的設定,設想一個情境,你手邊有一個沒有鬧鈴的鐘錶,還有一個沒有 鐘錶的鬧鈴,這個鬧鈴只能設定絕對時間,然後到期響鈴,你現在不知道幾點,可是你要睡覺並且得到通知必須在四個小時後去參加一個聚會,那麼你現在要做什 嗎?你肯定要看看你的鐘錶,然後設定你的鬧鐘。
以上的例子中,鐘錶就是clocksource,而鬧鐘就是clock_event_device,前者提供了一個指示盤,後者封裝了鬧鈴到期以後的行為 以及設定鬧鈴的把手,就好像你的鬧鈴都有旋鈕一樣。既然作業系統的行為是時鐘中斷驅動的,那麼它很符合我剛才例子中的那個邏輯,即使不用在核心中抽象出 clocksource和clock_event_device這些概念,只要能做到定時“響鈴”,然後去執行時鐘中斷就可以了,2.6.18之前的核心 中在沒有抽象出“鐘錶”和“鬧鈴”的情況下實現了上述的邏輯,可是這種方式有一個預設的前提就是核心一直有事可做,軟體是硬體的奴隸,不得不在硬體的預設 前提下每隔一個時間段就被中斷一次,而硬體只管定時中斷而不管到底是否真正有事可做,理想的實現應該是將定時的任務交給核心自己,就好比我希望定一個鬧鈴 到一定時間後叫醒我,我希望我自己定這個鬧鈴而不是希望到時間我正在熟睡而被不知情的叫醒,2.6.18以前的核心中,根本就沒有簡單的“定鬧鈴”的把 手,因此不得不忍受硬體的有事無事的定時中斷。clocksource和clock_event_device被抽象出來以 後,clock_event_device中有了定鬧鈴的把手,一切就醒目多了,實際上clocksource和clock_event_device被 抽象出來並不是為了nohz,而是為了將時鐘相關的代碼從平台相關的代碼中分離出來,以便於獨立修改統一管理,否則需要維護很多平台的不同的時鐘處理代 碼,而這些代碼的邏輯大致相同,隨後的2.6.22以後,nohz才出現,nohz其實就是託了抽象出來的clocksource和 clock_event_device的福,因為nohz直接需要設定下一次的停機時間而不是使用系統無條件的預設的HZ中斷。 clock_event_device中的set_next_event就是定鬧鈴的把手,而event_handler則是可以讓你自己定義鬧鈴到期後 的事件,就好比手機定鬧鈴時可以選到期後播放的音樂一樣可以自訂事件處理回呼函數。
     cfs調度和HZ分離了,clocksource和clock_event_device封裝了時鐘以及其操作,以往的進程在特定的固定時間片內運行,時 鐘的定時中斷提供了時間片的監督工作,一切顯得十分和諧,可是系統核心本身就是沒有主權,一切都在硬體的安排下進行,clocksource和 clock_event_device被抽象出來以後,核心有了一定的主權,它可以在運行時設定硬體了,核心的運行和硬體的特性進一步解除耦合,核心不再 是奴隸了,它終於可以作為主人設定硬體本身了,cfs調度器之後,關於進程以及整個系統的運行特性徹底從底層硬體的時鐘中分離了,完全採用linux的邏 輯進行,再也不用受制於底層的時鐘以及時間片分配特性,linux可以按照自己的方式來進行調度,或者用自己的方式設定下一個中斷的到來時間,這難道還是 中斷嗎?中斷的含義就是非同步到來的事件,clock_event_device的set_next_event致使系統明確的知道下一個中斷什麼時候到 來,這其實沒有什麼不對,就是因為它是時鐘相關的,而時鐘中斷在老的版本的核心裡面的中斷間隔也是確定的。新的核心越來越多的將硬體把手抽象給核心,或者 將核心把手抽象給使用者,這樣的核心顯得越來越成熟了,核心可以通過硬體把手操控硬體從而影響運行時的策略,而使用者可以通過核心把手操控核心從而影響核心的 運行時策略。核心對下面的硬體可以控制了,對上面的使用者空間也提供了很多不錯的操作介面,三層的聯絡越來越緊密但是卻沒有增加耦合性,實在是妙!
     clocksource是一個鐘錶,clock_event_device是一個鬧鈴,它們可以合并為一個鬧鐘,也可以單獨行動,既然 clock_event_device是一個鬧鐘而且必然擁有定鬧鈴的把手(set_next_event),那麼時鐘中斷就是由這個 clock_event_device來設定的了,設定的中斷到來以後,還是這個clock_event_device負責用event_handler 來唱一支歌,畢竟它是鬧鈴,鬧鈴要負責在到期後響鈴的,而且除了響鈴也可以做別的,而clocksource只是一個可以從中得到一個讀數的一個源頭罷 了,如果說誰要是有疑問,覺得如果一個clocksource沒有中斷功能卻成功的成了一個全域的主要clocksource,那麼怎麼辦?沒有問題,設 置中斷和clocksource有沒有中斷功能沒有關係,只要clock_event_device的set_next_event中有設定中斷硬體的邏 輯就可以了。比如tsc時鐘源沒有中斷功能,它是一個高精度計數器,那麼在系統的clock_event_device中的set_next_event 中必須實現設定當前中斷源的代碼。用clocksource和clock_event_device實現的新的時鐘邏輯更像是一個軟體定時器。
既然硬體時鐘可以由運行中的核心軟體驅動了,那麼很多機制都隨之變得靈活起來,比如hrtimer的實現,比如時鐘中斷的實現等等,在nohz模式中,在 cpu進入idle之前要進入ick_nohz_stop_sched_tick,這個函數中可能就會停掉時鐘中斷,如果停掉的話,那麼在每次其他硬體中 斷執行完之後會再次進入這個函數以檢測timer隊列是否被更新,或者定時器到期後,系統會重新開啟間隔為tick_period的時鐘中斷,這個可以用 hrtimer實現,也可以用別的機制實現。為了維持系統內cpu的負載平衡,所有開啟nohz停掉cpu的idle進程不能全部都停掉cpu進入 halt,而是要有一個進行idle load balance,為何不能讓別的cpu代勞呢?因為別的cpu忙著呢?只要處於idle狀態的cpu比較閑,因此就由它來負責所有的停掉的cpu的負載均 衡工作,一旦有進程被拉到了這些cpu上,那麼馬上喚醒它們,這在load_balance函數代碼中有描述:
if (ld_moved && this_cpu != smp_processor_id())
    resched_cpu(this_cpu);
以上的片段就是說一旦有進程拉到了this_cpu上並且這個cpu不是當前的執行load_balance的cpu,那麼就發送ipi喚醒處於nohz停止狀態的cpu,因為由於系統不平衡,它已經不能再繼續睡下去了。
前面一篇文章說了,由於2.6.23之前的核心的進程調度只要是基於時間片的,而時間片的計算又沒有辦法找到一種比較統一的方式,這個原因就是核心對硬體 的控制力弱加上作業系統核心的抽象機制嚴重依賴底層的硬體設定,你可以將HZ設定到1000甚至更高(HZ不能隨意高,必須依照cpu硬體來設定,HZ能 設定多高不在於你的代碼多高效,而是在於你的cpu有多快),可是你卻要面對新的問題,比如時間片跨度太大的響應慢問題,時間片跨度太小導致的高優先順序進 程不怎麼優先問題或者低優先順序時間片和HZ相關並且有時過小導致的cache頻繁失效問題,雖然雙斜率機制解決了部分問題,可是又引入了新的問題,比如 nice 0兩端不對稱問題。在新的cfs中,調度行為不再依賴HZ的值,並且在時鐘相關的操作抽象成clocksource和 clock_event_device之後,底層的時鐘硬體不再被在start_kernel中一次性的設定,而且被封裝了,可以隨時設定,新的設定方式 顯得更加直觀。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.