O1調度器仍然是根據經典的時間片分配的思路來進行整體設計的。簡單來說,時間片的思路就是將CPU的執行時間分成一小段一小段的,假如是5ms一段。于是多個進程如果要“同時”執行,實際上就是每個進程輪流占用5ms的cpu時間,而從1s的時間尺度上看,這些進程就是在“同時”執行的。當然,對于多核系統來說,就是把每個核心都這樣做就行了。而在這種情況下,如何支持優先級呢?實際上就是將時間片分配成大小不等的若干種,優先級高的進程使用大的時間片,優先級小的進程使用小的時間片。這樣在一個周期結速后,優先級大的進程就會占用更多的時間而因此得到特殊待遇。O1算法還有一個比較特殊的地方是,即使是相同的nice值的進程,也會再根據其CPU的占用情況將其分成兩種類型:CPU消耗型和IO消耗性。典型的CPU消耗型的進程的特點是,它總是要一直占用CPU進行運算,分給它的時間片總是會被耗盡之后,程序才可能發生調度。比如常見的各種算數運算程序。而IO消耗型的特點是,它經常時間片沒有耗盡就自己主動先釋放CPU了,比如vi,emacs這樣的編輯器就是典型的IO消耗型進程。
為什么要這樣區分呢?因為IO消耗型的進程經常是跟人交互的進程,比如shell、編輯器等。當系統中既有這種進程,又有CPU消耗型進程存在,并且其nice值一樣時,假設給它們分的時間片長度是一樣的,都是500ms,那么人的操作可能會因為CPU消耗型的進程一直占用CPU而變的卡頓??梢韵胂?,當bash在等待人輸入的時候,是不占CPU的,此時CPU消耗的程序會一直運算,假設每次都分到500ms的時間片,此時人在bash上敲入一個字符的時候,那么bash很可能要等個幾百ms才能給出響應,因為在人敲入字符的時候,別的進程的時間片很可能并沒有耗盡,所以系統不會調度bash程度進行處理。為了提高IO消耗型進程的響應速度,系統將區分這兩類進程,并動態調整CPU消耗的進程將其優先級降低,而IO消耗型的將其優先級變高,以降低CPU消耗進程的時間片的實際長度。已知nice值的范圍是-20-19,其對應priority值的范圍是100-139,對于一個默認nice值為0的進程來說,其初始priority值應該是120,隨著其不斷執行,內核會觀察進程的CPU消耗狀態,并動態調整priority值,可調整的范圍是+-5。就是說,最高其優先級可以唄自動調整到115,最低到125。這也是為什么nice值叫做靜態優先級而priority值叫做動態優先級的原因。不過這個動態調整的功能在調度器換成CFS之后就不需要了,因為CFS換了另外一種CPU時間分配方式,這個我們后面再說。
再簡單了解了O1算法按時間片分配CPU的思路之后,我們再來結合進程的狀態簡單看看其算法描述。我們都知道進程有5種狀態:
S(Interruptible sleep):可中斷休眠狀態。
D(Uninterruptible sleep):不可中斷休眠狀態。
R(Running or runnable):執行或者在可執行隊列中。
Z(Zombie process):僵尸。
T(Stopped):暫停。
在CPU調度時,主要只關心R狀態進程,因為其他狀態進程并不會被放倒調度隊列中進行調度。調度隊列中的進程一般主要有兩種情況,一種是進程已經被調度到CPU上執行,另一種是進程正在等待被調度。出現這兩種狀態的原因應該好理解,因為需要執行的進程數可能多于硬件的CPU核心數,比如需要執行的進程有8個而CPU核心只有4個,此時cpu滿載的時候,一定會有4個進程處在“等待”狀態,因為此時有另外四個進程正在占用CPU執行。
根據以上情況我們可以理解,系統當下需要同時進行調度處理的進程數(R狀態進程數)和系統CPU的比值,可以一定程度的反應系統的“繁忙”程度。需要調度的進程越多,核心越少,則意味著系統越繁忙。除了進程執行本身需要占用CPU以外,多個進程的調度切換也會讓系統繁忙程度增加的更多。所以,我們往往會發現,R狀態進程數量在增長的情況下,系統的性能表現會下降。系統中可以使用uptime命令查看系統平均負載指數(load average):
其中load average中分別顯示的是1分鐘,5分鐘,15分鐘之內的平均負載指數(可以簡單認為是相映時間范圍內的R狀態進程個數)。但是這個命令顯示的數字是絕對個數,并沒有表示出不同CPU核心數的實際情況。比如,如果我們的1分鐘load average為16,而CPU核心數為32的話,那么這個系統的其實并不繁忙。但是如果CPU個數是8的話,那可能就意味著比較忙了。但是實際情況往往可能比這更加復雜,比如進程消耗類型也會對這個數字的解讀有影響??傊?,這個值的絕對高低并不能直觀的反饋出來當前系統的繁忙程度,還需要根據系統的其它指標綜合考慮。
原文轉自:http://www.testwo.com/article/659