linux核心--進程調度

來源:互聯網
上載者:User

標籤:處理器   作業系統   linux   

      調度程是核心的組成部分,它負責選擇下一個要啟動並執行進程。進程發送器可看作在可運行態進程之間分配有限的處理器時間的核心子系統。Linux是一個多任務作業系統,只有通過發送器的合理調度,系統資源才能最大限制的發揮作用,多進程才會有並發執行的效果。

       多任務作業系統分為非搶佔式多任務和搶佔式多任務。linux是一個搶佔式的多任務作業系統,由發送器決定什麼時候停止一個進程的運行以便其它進程能夠得到執行機會,這個強制的掛起動作就叫做搶佔。進程在被搶佔之前能夠啟動並執行時間是預先設定好的,叫進程的時間片。時間片實際是分配給每個可啟動並執行進程的處理器時間段。而在非搶佔式多任務模式下,除非進程自己主動停止,否則它會一直執運行。

策略

      策略決定發送器在何時讓什麼進程運行。進程可以分為I/O消耗型和處理器消耗型。前者指進程的大部分時間用來提交I/O請求或等待I/O請求。因此,這樣的進程經常處理可運行狀態,但通常都是運行短短一會兒,因為它在等待更多的I/O請求時最後總會阻塞。相反,處理消耗型進程把時間大多用在執行代碼上。除非被搶佔,否則它們通常一直不停地運行,因為它們沒有太多的I/O需求。對於這類處理消耗型的進程,調度策略是盡量降低它們的運行頻率,對於它們而言,延長其已耗用時間會更合適些。

      調度策略通常在兩個矛盾的目標中間尋找平衡:進程響應迅速(回應時間短)和最大系統利用率(高輸送量)。調度演算法中最基本的一類就是基於優先順序的調度。優先順序高的先運行,低的後運行,相同優先順序的進程按輪轉方式進去調 度(一個接一個,重複進行)。在包括Linux在內的某些作業系統中,優先順序高的進程使用的時間片也較長。發送器總是選擇時間片未用盡且優先順序高的進程運行。使用者和系統都可以通過設定進程的優先順序來影響系統的調度。

      Linux根據以上思想實現了一種基於動態優先順序的調度方法。一開始,該方法先設定基本的優先順序,然而它允許發送器根據需要來加、減優先順序。舉個例子,如果一個進程在I/O等待上耗費的時候多於其已耗用時間,那麼該進程顯屬於I/O消耗型進程。它的優先順序會被動態提高。相反,如果一個進程的全部時間片一下就被耗盡,那麼該進程屬於處理器消耗型進程,它的優先順序會被動態降低。

      時間片是一個數值,它表時進程在被搶佔前所能持續啟動並執行時間。調 度策略必須規定一個預設的時間片,時間片過長會導致系統對互動的響應表現欠佳;讓人覺得系統無法並發執行應用程式;時間片過短會明顯增大進程切換帶來的消耗,因為肯定會有相當一部分系統時間用在進程切換上,而這些進程能夠用來啟動並執行時間片卻很短。當一個進程的時間片耗盡時,就認為這個進程到期了。

       linux系統是搶佔式的,當一個進程進入task_running狀態,核心會檢查它的優先順序是否高於當前正在執行的進程。如果是這樣,發送器會被喚醒,搶佔當前正在啟動並執行進程並運行新的可運行進程。此外,當一個進程的時間片變為0時,它會被搶佔,發送器被響醒以選擇一個新的進程。

發送器的可執行隊列

      發送器中最基本的資料結構是運行隊列,可執行隊列是給處理器上的可執行進程的鏈表,每個處理器一個。每個可投入執行的進程都惟一歸屬於一個可執行隊列。每個運行隊列都有兩個優先順序數組,一個活躍的和一個到期的。優先順序數組使可運行處理器的每一種優先順序都包含一個相應的隊列,而這些隊列包含對應優先順序上的可執行進程鏈表。

       許多作業系統在所有進程的時間片用完時,都採用一種顯式的方法來重新計算每個進程的時間片。當一個進程的時間片耗盡時,它會被移至到期數組,但在此之前,時間片已經給它重新計算好了。

       選定一個進程並切換到它去執行是通過schedule()函數來實現的。當核心想要休眠時,會直接調用函數,另外,如果有哪個進程被搶佔,那麼該函數也會被喚起執行。schedule()函數獨立於每一個處理器運行。因此,每個處理器對下一次該運行哪個進程做出自己的判斷。

       發送器通過進程的休眠時間來判斷一個進程到底是I/O消耗型還是處理消耗型。為了支援這種推斷機制,linux記錄了一個進程用於休眠和用於執行的時間,這個值存在於task_struct的sleep_avg域中。

       休眠(被阻塞)的進程處理一個特殊的不可執行狀態。進程休眠有各種原因,但肯定是為了等待一些事件。事件可能是一段時間、從檔案I/O讀更多資料,或者是某個硬體事件。休眠的一個常見原因就是檔案I/O--如進程對一個檔案執行了read()操作,而這需要從磁碟裡讀取。還有,進程在擷取鍵盤輸入的時候也需要等待。無論哪種情況,核心的操作都相同:進程把它自已標幟為休眠狀態,把自己從可執行隊列移出,放入等待隊列,然後調用schedule()選擇和執行一個其它進程。喚醒的過程剛好相反:進程被設定為可執行狀態,然後再從等待隊列中移到可執行隊列。

休眠和喚醒狀態圖

650) this.width=650;" title="休眠和喚醒切換圖" style="border-top: 0px; border-right: 0px; border-bottom: 0px; border-left: 0px; display: inline" border="0" alt="休眠和喚醒切換圖" src="http://img1.51cto.com/attachment/201409/7/817917_141006560760Ru.jpg" "532" height="336" />

 

Server Load Balancer程式

linux的發送器為對稱多下得系統的每個處理器準備了單獨的可執行隊列和鎖,也就是說,每個處理器擁有一個自己的進程鏈表,而它只對屬於自己的這些進程進行調度操作。出地效率考慮,整個調度系統從每個處理器來看都是獨立的。如果出現一個處理器的隊列上有5個進程,而另外一個處理器的隊列上只有1個進程,該怎麼辦呢?這些問題由Server Load Balancer程式解決,它負責保證可執行隊列之間的Server Load Balancer狀態。如果發現了不均衡,就會把相對繁忙的隊列中的進程抽到當前的可執行隊列中來。理想狀態下,每個隊列上的進程數目應該相等。在單一處理器系統中,不會執行負載平衡程式。

搶佔和環境切換

      環境切換,也就是從一個可執行進程切換到另一個可執行進程。每當一個新的進程被選出來準備投入啟動並執行時候,schedule()就會調用環境切換功能函數context_switch()。

即時

linux提供了兩種即時調度策略:SCHED_FIFO和SCHED_RR。而普通的、非即時的調度策略是SCHED_NORMAL。SCHED_FIFO實現了一種簡單的、先入先出的調度演算法,它不使用時間片。SCHED_FIFO級的進程比任何SCHED_NORMAL級的進程都先得到調度。一旦一個SCHED_FIFO級進程處於可執行狀態,應該會一直執行,直到它自己受阻塞或顯示的釋放處理器為止,它不基於時間片,可以一直執行下去。只有較高優先順序的SCHED_FIFO或SCHED_RR任務才能搶佔SCHED_FIFO任務。如果有兩個或者更多的SCHED_FIFO進程,它們會輪流執行。SCHED_RR與SCHED_FIFO大體相同,只是SCHED_RR級的進程在耗盡事先分配給它的時間後就不能再接著執行了。這兩種即時演算法實現的都是靜態優先順序。

linux核心--進程調度

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.