引言
當計算機系統處于就緒狀態的用戶進程數多于CPU數時,就會產生多個進程或線程同時競爭CPU的結果。假設現在只有一個CPU可用,那么操作系統就必須選擇下一個要運行的進程。完成這種選擇工作的這一部分稱為調度程序,該程序使用的算法稱為調度算法。
盡管有一些不同,但許多適用于進程調度的處理方法也同樣適用于線程調度。當內核管理線程的時候,調度經常是按線程級別的,與線程所屬的進程基本或根本沒有關聯。
調度時機
在執行具體的調度程序之前,操作系統必須要解決一個關鍵的問題:何時進行調度決策?
有以下情形需要調度處理:
1、 在創建一個新進程之后,需要決定是運行父進程還是運行子進程。由于這兩種進程都處于就緒狀態,所以這是一種正常的調度決策,可以任意決定。
2、在一個進程退出時必須做出調度決策。一個進程不再運行,所以必須從就緒進程集中選擇另外某個進程。如果沒有就緒的進程,通常會運行一個系統提供的空閑進程。
3、當一個進程在阻塞I/O和信號量上或由于其他原因阻塞時,必須選擇另一個進程運行。
4、在一個I/O中斷發生時,必須做出調度決策。如果中斷來自I/O設備,而該設備現在完成了工作,某些阻塞的等待該I/O進程就成為可運行的就緒進程了。是否讓新就緒的進程運行,這取決于調度程序的決定 ,或者讓中斷發生時運行的進程繼續運行,或者應該讓某個其他進程運行。
注:區分一個多任務分時系統是搶占式的還是非搶占式的,則要看進程能否在(4)發生中斷時,能否產生調度(搶占)。
調度算法的分類
根據如何處理時鐘中斷,可以把調度算法分為兩類:搶占式或非搶占式
搶占式
搶占式調度算法挑選一個進程,并且讓該進程運行某個固定時段的最大值。如果在該時段結束時,該進程仍在運行,它就被掛起,而調度程序挑選另一個進程運行(如果存在一個就緒進程)。進行搶占式調度處理,需要在時間間隔的末端發生時鐘中斷,以便把CPU控制返回給調度程序,如果沒有可用的時鐘,那么非搶占式調度就是惟一的選擇了。
這里有一個有趣的問題,就是這個固定時段的最大值設置為多少合適?
假如進程切換需要5毫秒,最大值為20毫秒,那么在做完20毫秒有用的工作之后,CPU將花費5毫秒來進行進程切換,在100毫秒內CPU時間就有20%被浪費在了進程切換上。
為了提高CPU效率,我們將最大值設為500毫秒,這時浪費的時間只有1%。但考慮在一個分時系統中,如果有十個交互用戶幾乎同時按下回車鍵,將發生什么情況?假設所有其他進程都用足它們的時間,最后一個不幸的進程不得不等待5秒鐘才獲取運行機會,這通常是用戶無法忍受的。
所以這里得出一個結論:時間設得太短會導致過多的進程切換,降低CPU效率;而設得太長又可能引起對短的交互請求的響應變差。將時間片設為20ms-50ms通常是一個比較合理的折中。
非搶占式
非搶占式調度算法挑選一個進程,然后讓該進程運行直至阻塞(阻塞在I/O上或等待另一個進程),或者直到該進程自動釋放CPU。即使該進程運行了若干個小時,它也不會被強迫掛起。這樣做的結果是,在時鐘中斷發生時不會進行調度。在處理完時鐘中斷后,如果沒有更高優先級的進程等待到來,則被中斷的進程會繼續執行。
非搶占式調度最大的問題就是:每個進程需要多少CPU時間就占用多少CPU時間,只有進程主動釋放CPU時,其他的進程才可以使用CPU。假如一個進程在執行一個耗時的操作,這就使其它進程一直處于“餓死”狀態。
注:Windows3.x是使用的非搶占式,Windows95以后及UNIX,Linux最新內核(參見)都是使用的搶占式。
系統分類
不同的系統環境需要不同的調度算法,我們常常把系統分為以下三類
批處理系統
批處理系統,又名批處理操作系統。
所謂批處理是指用戶將作業按照它位的性質分組(或分批),然后再成組(或成批)地提交給計算機系統,由計算機自動完成后再輸出結果,從而減少作業建立和結束過程中的時間浪費。根據存放的作業數又可以將批處理系統分為:
- 單道批處理系統
- 多道批處理系統
具體參見。
在批處理系統中,不會有用戶有不耐煩地在終端旁等待一個短請求的快捷響應。因此,非搶占式算法,或對每個進程都有長時間周期的搶占式算法,通常都是可以接受的。這種處理方式減少了進程的切換從而改善性能。
交互式系統
交互式操作系統是為達到人機交互目的而為機器所編寫的操作系統。常見的交互操作系統有Windows,DOS等,在交互式系統當中,最常見的應該是:分時操作系統。
分時操作系統
在操作系統中采用分時技術的系統被稱為分時系統,分時操作系統也被稱為“事務處理使用的交互式操作系統”。
所謂分時技術就是把處理器的運行時間分成很短的時間片,按時間片輪流把處理器分配給各聯機作業使用。若某個作業在分配給它的時間片內不能完成其計算,則該作業暫時停止運行,把處理器讓給其他作業使用,等待下一輪再繼續運行。由于計算機速度很快,作業運行輪轉得很快,給每個用戶的感覺好像是自己獨占一臺計算機。
在交互式用戶環境中,為了避免一個進程霸占CPU拒絕為其他進程服務,搶占是必震的。即便沒有進程想永遠運行,但是,某個進程由于一個程序錯誤也可能無限期的排斥所有其他進程。為了避免這種現象發生,搶占也是必要的。服務器也歸于此類,因為通常它們要服務多個突發的(遠程)用戶。
實時系統
為了能在某個時間限制內完成某些緊急任務而不需時間片排除,誕生了實時操作系統。這里面的時間限制可以分為兩種情況:
1、如果某個動作必須絕對地在規定的時刻(或規定的時間范圍)發生,則稱為硬實時系統。例如,飛行器的飛行自動控制系統,這類系統必須提供絕對保證,讓某個特定的動作在規定的時間內完成。
2、如果能夠授受偶爾違反時間規定,并且不會引起任何永久性傷害,則稱為軟實時系統,如飛機訂票系統,銀行管理系統。
在實時操作系統的控制下,計算機系統接收到外部信號后及時進行處理,并且要在嚴格的時限內處理完成接收事件。
在實時操作系統中,搶占有時是不需要的,因為進程了解它們可能會長時間得不到運行,所以通常很快地完成各自的工作并阻塞。實時系統與交互式系統的差別是,實時系統只運行那些用來推進現有應用的程序,而交互式系統是通用的,它可以運行任意的非協作甚至是有惡意的程序。
實時操作系統的主要特點是及時性和可靠性。
調度算法的目標
為了設計調度算法,有必要考慮什么是一個好的調度算法?某些目標取決于環境(批處理、交互式或實時),但是還有一些目標是適用于所有情形的。
1、所有系統
- 公平:給每個進程公平的CPU份額
相似的進程應該得到相似的服務。對一個進程給予較其他等價的進程更多的CPU時間是不公平的。當然,不同類型的進程可以采用不同的處理方式。 - 策略強制執行:看到所宣布的策略執行
如果局部策略是,只要需要就必須運行安全控制進程(即便這意味著推遲30秒鐘發薪),那么調度程序就必須保證能夠強制執行該策略。 - 平衡:保持系統的所有部分都忙碌
如果CPU和所有I/O設備能夠始終的運行,那么相對于讓某些部件空轉而言,每秒鐘就可以完成更多的工作。
例如,在批處理系統中,調度程序控制哪個作業調入內存運行。在內存中既有一些CPU密集型進程又有一些I/O密集型進程是一個較好的想法。如果先調入所有CPU密集型進程,完成之后再調入所有I/O密集型進程,那么當CPU密集型進程運行時,它們就要競爭CPU,而磁盤卻在空轉。當I/O密集型進程運行時,它們又要競爭磁盤,而CPU又在空轉。
2、批處理系統
- 吞吐量:每小時最大作業數
把所有的因素考慮進去之后,每小完成50個作業好于每小時完成40個作業。 - 周轉時間:從提交到終止間的最小時間
該數據度量了用戶要得到輸出所需的平均等待時間,時間越小越好。 - CPU利用率:保持CPU始終忙碌
3、交互式系統
- 響應時間:快速響應請求
- 均衡性:滿足用戶的期望
用戶對做一件事情需要多長時間總是有一種固有的看法(不過通常不正確)。當認為一個請求很復雜需要較多時間時,用戶會接受這個看法,但是當認為一個請求很簡單,但也需要較多的時間時,用戶就會急躁。
4、實時系統
- 滿足截止時間:避免丟失數據
實時系統的特點是或多或少必須滿足截止時間。例如,如果計算機正在控制一個以正常速率產生數據的設備,若一個按時運行的數據收集進程出現失敗,會導致數據丟失。所以,實時系統最主要的要求是滿足所有的(或大多數)截止時間要求。 - 可預測性: 在多媒體系統中避免品質降低。
在多數實時系統中,特別是那些涉及多媒體的實時系統中,可預測性是很重要的。偶爾不能滿足截止時間要求的問題并不嚴重,但是如果音頻進程運行的錯誤太多,那么音質就會下降得很快。為了避免這些問題,進程調度程序必須是調度可預測和有規律的。
調度策略
1、先來先服務(FCFS、非搶占式)
使用該算法,進程按照它們請求CPU的順序使用CPU。基本上,有一個就緒進程的單一隊列。當第一個作業從外部進入系統,就立即開始并允許運行它所期望的時間。不會中斷該作業,因為它需要很長的時間運行。當其也作業進入時,它們就被安排到隊列的尾部。當正在運行的進程被阻塞時,隊列中的第一個進程就接著運行。在被阻塞的進程變為就緒時,就像一個新來到的作業一樣,排到隊列未尾。
優點:易于理解并且便于在程序中運用。在這個算法中,一個單鏈表記錄了所有就緒進程。要選取一個進程運行,只要從該隊列的頭部移走一個進程即可;要添加一個新的作業或阻塞一個進程,只要把該作業或進程附加在相應隊列的末尾即可。
缺點:CPU和I/O設備得不到充分利用。
假如,有一個一次運行1秒鐘的CPU密集型進程和每個都要進行1000次磁盤讀操作的I/O密集型進程存在。CPU密集型進程運行1秒鐘,接著I/O密集型進程開始讀一個磁盤塊,此時它將會被阻塞,加入到隊列未尾。CPU密集型進程接著運行,依次循環,這樣I/O密集型進程就要要等1000秒鐘才能完成操作。如果有一個調度算法每10ms搶占計算密集型進程,那么I/O進程將在10秒鐘內完成而不是1000秒鐘,而且還不會對計算密集型進程產生多少延遲。
2、最短作業優先(SJF、非搶占式)
進程開始獲取CPU一直運行直到完成或者由于某事件被阻塞放棄CPU,運行結束后從當前就緒隊列選擇“最短”的進程運行。該調度算法適用于運行時間可以預知的任務。
優點:可以有效減少周轉時間
假如有A、B、C、D四個進程,分別要執行A(8),B(4),C(4),D(4)分鐘,按照原有次序運行作業:
則A的周轉時間為8分鐘,B為12分鐘,C為16分鐘,D為20分鐘,平均(8+12+16+20)/4=14分鐘
如果按照最短作業優先次序運行:
則B的周轉時間為4分鐘,C為8分鐘,D為12分鐘,A為20分鐘,平均(4+8+12+20)/4=11分鐘
缺點:利用短進程,長進程可能由于得不到CPU,而“餓死”。
有必要指出,只有在所有作業都可同時運行的情形下,最短作業優先算法才是最優化的。作為一個反例,考慮5個作業,從A到E,運行時間分別是2、4、1、1和1。它們的到達時間是0、0、3、3和3。 開始只能選擇A或B,因為其他三個作業還沒有到達。使用最短作業優先,將按照A、B、C、D、E的順序運行作業,其平均等待時間是4.6。但是,按照B、C、D、E、A的順序運行作業,其平均等待時間則是4.4。
3、最高響應比優先(HRP、非搶占式)
進程開始獲取CPU一直運行直到完成或由于某事件被阻塞放棄CPU,運行結束從當前就緒隊列選擇最高響應比的進程投入運行。
響應比=(響應時間+運行時間)/運行時間
在響應時間固定的情況下,利于短進程。長進程隨著等待時間變長,響應比會提高,因此長進程也能在足夠長的時間被調度。
優缺點:利用短進程、長進程不會被餓死。
4、最短剩余時間(SRT、搶占)
使用這個算法,調度程序總是選擇剩余運行時間最短的那個進程運行。有關的運行時間必須提前掌握。當一個新的作業到達時,其整個時間同當前進程剩余時間做比較。如果新的進程比當前運行進程需要更少的時間,當前進程就被掛起,而運行新的進程。
優缺點:利于短進程,開銷大,不利于長進程。
5、輪轉調度
每個進程被分配一個時間段,稱為時間片,即允許該進程在該時間段中運行。如果在時間片結束時該進程還在運行,則將剝奪CPU并分配給另一個進程。如果該進程在時間片結束前阻塞或結束,則CPU立即進行切換。
時間片輪轉調度很容易實現,調度程序所要做的就是維護一張可運行進程列表,如下圖
當一個進程用完它的時間片后,就被移到隊列的末尾,如下圖
此算法是最古老、最簡單、最公平且使用最廣的算法
6、優先級調度
輪轉調度做了一個隱含的假設,即所有的進程同等重要,而擁有和操作多用戶計算機系統的人對此有不同的看法。例如,在一所大學里,等級順序可能是教務長首先,然后是教授、秘書、后勤人員,最后是學生。這種將外部因素考慮在內的需要就導致了優先級調度。其基本思想很清楚:每個進程被賦予一個優先級,允許優先級最高的可運行進程先運行。
為了防止高優先級進程無休止地運行下去,調度程序可以在每個時鐘滴答(即每個時鐘中斷)降低當前進程的優先級。如果這個動作導致該進程的優先級低于次高優先級的進程,則進行進程切換。一個可采用的方法是,每個進程可以被賦予一個允許運行的最大時間片,當這個時間片用完時,下一個次高優先級的進程獲得機會運行。
優先級可以靜態賦予或動態賦予。例如可以將一個進程的優先級設為100,也可以將一個進程的優先級設為1/f(f為該進程在上一時間片中所占的部分)。
可以很方便地將一組進程按優先級分成若干類,并且在各類之間采用優先級調度,而在各類進程的內部采用輪轉調度。如圖:
其調度算法如下:
只要存在優先級為第4類的可運行進程,就按照輪轉法為每個進程運行一個時間片,此時不理會較低先級的進程。若第4類進程為空,則按照輪轉法運行第3類進程。若第4類和第3類均為空,則按輪轉法運行第2類進程。如果不偶爾對優先級進行調整,則低優先級進程很可能會產生饑餓現象。
除了上面介紹的幾種算法以外,還有多級隊列,多級反饋隊列,保證調度,彩票調度等算法,此處不再一一的進行介紹,詳細可見參考資料。
策略和機制
到目前為止,我們隱含地假設系統中所有進程分屬不同的用戶,并且,進程間相互競爭CPU。通常情況下確實如此,但有時也有這樣的情況:一個進程有許多子進程并在共控制下運行。例如,一個數據庫管理系統可能有許多子進程,每一個子進程可能處理不同的請求,或每一個子進程實現不同的功能(如請求分析,磁盤訪問等)。主進程完全可能掌握哪一個子進程最重要(或最緊迫)而哪一個最不重要。但是,以上討論的調度算法中沒有一個算法從用戶進程接收有關的調度決策信息,這就導致了調度程序很少能夠做出最優的選擇。
解決問題的方法是將調度機制與調度策略分離,也就是將調度算法以某種形式參數化,而參數可以由用戶進程填寫。我們再來看一下數據庫的例子。假設內核使用優先級調度算法,但提供一條可供進程設置(并改變)優先級的系統調用。這樣,盡管父進程本身并不參與調度,但它可以控制如何調度子進程的細節。在這里調度機制位于內核,而調度策略則由用戶進程決定。
參考資料
1、《現代操作系統》
2、 http://www.cnblogs.com/riskyer/p/3249337.html
3、http://blog.csdn.net/kavensu/article/details/8075642
4、http://blog.csdn.net/u010889616/article/details/48424501
5、http://baike.baidu.com/item/%E6%97%B6%E9%97%B4%E7%89%87%E8%BD%AE%E8%BD%AC%E8%B0%83%E5%BA%A6%E7%AE%97%E6%B3%95/7170554
6、http://blog.csdn.net/russell_tao/article/details/7103012