天天看點

Windows線程排程機制

      今天複習作業系統,覺着windows的線程排程政策應該寫在一起,加上一個整體的認識比較好,就來寫篇部落格也當做複習筆記了,有些地方可能略顯零散。

    Windows 實作了一個由優先級驅動,搶占式的排程系統,排程過程結合實踐配額調整,排程機關是線程。Windows 在單處理機系統和多處理機系統中的線程排程是不同的。

    Windows采用多優先級隊列,windows為每個優先級的線程都準備了優先級隊列,同一優先級各線程按時間片輪轉進行排程,多處理器可以多線程并行。

    Windows的沒有單獨的排程子產品或程式,排程的代碼是在核心中實作的,廣泛分布在核心中那些與排程相關的事件發生的地方。這些負責排程的程式被總稱為“核心的排程器”。線程排程發生在DPC/Dispatch級别。

以下這些事件發生時會觸發線程排程:

  • 變成就緒狀态的線程。例如:一個新建立的線程,或者從等待狀态釋放出來的線程。
  • 因其時間片結束而離開運作狀态的線程,它或者結束了,或者進入等待狀态。
  • 線程的優先級改變了,是因為系統調用,或者是Windows自己改變了優先級。
  • 正在運作的線程的處理器親合性改變了。

    Windows内部使用32個優先級别,從0-31。這些數值被分成以下幾類:

  • [實時優先級]16個實時級别(16-31)
  • [動态優先級]15個變化的級别(1-15) (一般互動式線程優先級最高)
  • 1個系統級别(0), 被保留用作0頁線程(零頁線程:用于對系統中空閑實體頁面清零)

    需要注意的是Windows這裡的實時優先級隻是一種windows内部的命名(windows很多的指令和理論課或unix中的命名不同),并不是通常意義上的實時。

    對于具備實時優先級的線程在被其他線程搶占時,具有實時優先級線程與具有可變優先級線程的行為是不同的,下面會介紹到。在應用程式中,使用者可在一定範圍内升高或降低線程優先級,但要把線程的優先級提升到實時優先級,使用者必須有升高線程優先級的權限,如果使用者程序在實時優先級運作時間過多,可能阻塞關鍵系統功能的執行,阻塞系統線程的運作。

在Win32 API中,每個線程的優先級都是它所屬的程序的優先級和自己相關的線程優先級二者的組合。從Win32優先級映射到Windows内部數字式的優先級如圖所示:

(轉載自http://www.programfan.com/blog/article.asp?id=44350)

Windows線程排程機制

   前面提到了一個概念叫做時間配額,時間配額不是一個時間長度值,而一個稱為配額機關的整數。(每次從檢查排程間的運作時間,很好了解,不多解釋)多說一下,時間配額的作用就是可以在不提升優先級的情況下區分不同線程的運作時間,如果提升優先級來做可能導緻一些線程饑餓。

   排程方式有三種:

  • 主動切換
  • 搶占(當線程被搶占時,它被放回到相應的優先級就緒隊列的隊首;對實時優先級線程被搶占後配置設定一個完整的是時間配額,而動态優先級線程不變,下次僅運作剩餘時間配額)
  • 時間配額用完(沒有同優先級線程會繼續配置設定一個新的時間配額)

    windows線程有優先級提升機制(總的來說是因為能更好利用CPU資源或饑餓而提高優先級):

  • I/O操作完成
  • 信号量或事件等待結束
  • 前台程序中的線程完成一個等待操作
  • 由于視窗活動而喚醒圖形使用者接口線程
  • 線程處于就緒狀态超過一定時間,但沒能進入運作狀态(處理機饑餓)

特别說明下饑餓狀态下的優先級提升: 系統線程“平衡集管理器(balance set manager)” 會每秒鐘檢查一次就緒隊列,是否存在一直在就緒隊列中排隊超過300個時鐘中斷間隔的線程。如果找到這樣的線程,平衡集管理器将把該線程的優先級提升到15,并配置設定給它一個長度為正常值4倍的時間配額。一旦運作完重新回到原來的優先級。

以上都是對于單核情況,對于多核的情況下假如有N個處理器,則N-1個處理器上活躍的線程為最高優先級的線程N-1個,獨占運作,剩下的低優先級線程會共享剩餘的一個處理器。但這個原則又收到處理器關聯屬性的影響。如果一個線程準備執行,但是唯一可用的處理器不在它的處理器關聯結合中,則該線程也隻能被迫等待,執行體排程下一個可以得到的線程執行。

繼續閱讀