這似乎不用過多的解釋,畢竟自從多任務操作系統誕生以來,進程執行占用cpu的能力就是一個必須要可以人為控制的事情。因為有的進程相對重要,而有的進程則沒那麼重要。
進程優先級起作用的方式從發明以來基本沒有什麼變化,無論是只有一個cpu的時代,還是多核cpu時代,都是通過控制進程占用cpu時間的長短來實現的。
就是說在同一個調度周期中,優先級高的進程占用的時間長些,而優先級低的進程占用的短些。
請大家真的不要混淆了系統中的這兩個概念:nice(NI)和priority(PR),他們有著千絲萬縷的關系,但對於當前的Linux系統來說,它們並不是同一個概念。
我們看這個命令:
大家是否真的明白其中PRI列和NI列的具體含義有什麼區別?
同樣的,如果是top命令:
大家是否搞清楚了這其中PR值和NI值的差別?如果沒有,那麼我們可以首先搞清楚什麼是nice值。
NICE值應該是熟悉Linux/UNIX的人很了解的概念了,它是反應一個進程“優先級”狀態的值,其取值范圍是-20至19,一共40個級別。
這個值越小,表示進程”優先級”越高,而值越大“優先級”越低。
例如,我們可以通過NICE命令來對一個將要執行的bash命令進行NICE值設置,方法是:
[root@zorrozou-pc0 zorro]# nice -n 10 bash
這樣我就又打開了一個bash,並且其nice值設置為10,而默認情況下,進程的優先級應該是從父進程繼承來的,這個值一般是0。
我們可以通過nice命令直接查看到當前shell的nice值:
[root@zorrozou-pc0 zorro]# nice 10
對比一下正常情況:
[root@zorrozou-pc0 zorro]# exit
退出當前nice值為10的bash,打開一個正常的bash,我們查看下其 Nice值:
[root@zorrozou-pc0 zorro]# bash
[root@zorrozou-pc0 zorro]# nice 0
另外,使用renice命令可以對一個正在運行的進程進行nice值的調整,我們也可以使用比如top、ps等命令查看進程的nice值,具體方法我就不多說了,大家可以參閱相關man page。
需要大家注意的是,我在這裡都在使用nice值這一稱謂,而非優先級(priority)這個說法。
nice值雖然不是priority,但是它確實可以影響進程的優先級。
在英語中,如果我們形容一個人nice,那一般說明這個人的人緣比較好。什麼樣的人人緣好?往往是謙讓、有禮貌的人。
比如,你跟一個nice的人一起去吃午飯,點了兩個一樣的飯,先上了一份後,nice的那位一般都會說:“你先吃你先吃!”,這就是人緣好,這人nice!但是如果另一份上的很晚,那麼這位nice的人就要餓著了。
這說明什麼?
越nice的人搶占資源的能力就越差,而越不nice的人搶占能力就越強。這就是nice值大小的含義,nice值越低,說明進程越不nice,搶占cpu的能力就越強,優先級就越高(作者這個解釋太形象了,小編忍不住要手動點贊!!)。
在原來使用O1調度的Linux上,我們還會把nice值叫做靜態優先級,這也基本符合nice值的特點,就是當nice值設定好了之後,除非我們用renice去改它,否則它是不變的。
而priority的值在之前內核的O1調度器上表現是會變化的,所以也叫做動態優先級。
我們再來看看什麼是priority值,就是ps命令中看到的PRI值或者top命令中看到的PR值。
本文為了區分這些概念,以後:
統一用nice值表示NI值,或者叫做靜態優先級,也就是用nice和renice命令來調整的優先級;
而實用priority值表示PRI和PR值,或者叫動態優先級。
我們也統一將“優先級”這個詞的概念規定為表示priority值的意思。
在內核中,進程優先級的取值范圍是通過一個宏定義的,這個宏的名稱是MAX_PRIO,它的值為140。
而這個值又是由另外兩個值相加組成的,一個是代表nice值取值范圍的NICE_WIDTH宏,另一個是代表實時進程(realtime)優先級范圍的MAX_RT_PRIO宏。
說白了就是,Linux實際上實現了140個優先級范圍,取值范圍是從0-139,這個值越小,優先級越高。nice值的-20到19,映射到實際的優先級范圍是100-139。
新產生進程的默認優先級被定義為:
#define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2)
實際上對應的就是nice值的0。
正常情況下,任何一個進程的優先級都是這個值,即使我們通過nice和renice命令調整了進程的優先級,它的取值范圍也不會超出100-139的范圍,除非這個進程是一個實時進程,那麼它的優先級取值才會變成0-99這個范圍中的一個。
這裡隱含了一個信息,就是說當前的Linux是一種已經支持實時進程的操作系統。
我們就不再這裡詳細解釋其含義以及在工業領域的應用了,有興趣的可以參考一下實時操作系統的維基百科。
簡單來說,實時操作系統需要保證相關的實時進程在較短的時間內響應,不會有較長的延時,並且要求最小的中斷延時和進程切換延時。
對於這樣的需求,一般的進程調度算法,無論是O1還是CFS都是無法滿足的,所以內核在設計的時候,將實時進程單獨映射了100個優先級,這些優先級都要高於正常進程的優先級(nice值),而實時進程的調度算法也不同,它們采用更簡單的調度算法來減少調度開銷。
總的來說,Linux系統中運行的進程可以分成兩類:
它們的主要區別就是通過優先級來區分的。
所有優先級值在0-99范圍內的,都是實時進程,所以這個優先級范圍也可以叫做實時進程優先級,而100-139范圍內的是非實時進程。
在系統中可以使用chrt命令來查看、設置一個進程的實時優先級狀態。我們可以先來看一下chrt命令的使用:
我們先來關注顯示出的Policy options部分,會發現系統給各種進程提供了5種調度策略。
但是這裡並沒有說明的是,這五種調度策略是分別給兩種進程用的,對於實時進程可以用的調度策略是:SCHED_FIFO、SCHED_RR,而對於非實時進程則是:SCHED_OTHER、SCHED_OTHER、SCHED_IDLE。
系統的整體優先級策略是:
實時進程可以指定的優先級范圍為1-99,將一個要執行的程序以實時方式執行的方法為:
[root@zorrozou-pc0 zorro]# chrt 10 bash
[root@zorrozou-pc0 zorro]# chrt -p $$
pid 14840's current scheduling policy: SCHED_RR
pid 14840's current scheduling priority: 10