1. 程式人生 > >linux的程序優先順序

linux的程序優先順序


為什麼要有程序優先順序?這似乎不用過多的解釋,畢竟自從多工作業系統誕生以來,程序執行佔用cpu的能力就是一個必須要可以人為控制的事情。因為有的程序相對重要,而有的程序則沒那麼重要。

程序優先順序起作用的方式從發明以來基本沒有什麼變化,無論是隻有一個cpu的時代,還是多核cpu時代,都是通過控制程序佔用cpu時間的長短來實現的。就是說在同一個排程週期中,優先順序高的程序佔用的時間長些,而優先順序低的程序佔用的短些。

從這個角度看,程序優先順序其實也跟cgroup的cpu限制一樣,都是一種針對cpu佔用的QOS機制。我曾經一直很困惑一點,為什麼已經有了優先順序,還要再設計一個針對cpu的cgroup?得到的答案大概是因為,優先順序這個值不能很直觀的反饋出資源分配的比例吧?

不過這不重要,實際上從核心目前的程序排程器cfs的角度說,同時實現cpushare方式的cgroup和優先順序這兩個機制完全是相同的概念,並不會因為增加一個機制而提高什麼實現成本。既然如此,而cgroup又顯得那麼酷,那麼何樂而不為呢?

在系統上我們最熟悉的優先順序設定方式是nice和renice命令。那麼我們首先解釋一個概念,什麼是:

NICE值

nice值應該是熟悉Linux/UNIX的人很瞭解的概念了,我們都知它是反應一個程序“優先順序”狀態的值,其取值範圍是-20至19,一共40個級別。這個值越小,表示程序”優先順序”越高,而值越大“優先順序”越低。我們可以通過nice命令來對一個將要執行的命令進行nice值設定,方法是:

1

這樣我就又打開了一個bash,並且其nice值設定為10,而預設情況下,程序的優先順序應該是從父程序繼承來的,這個值一般是0。我們可以通過nice命令直接檢視到當前shell的nice值

1
[root@zorrozou-pc0 zorro]# nice
2
10

對比一下正常情況:

1

推出當前nice值為10的bash,開啟一個正常的bash:

1
[root@zorrozou-pc0 zorro]# bash
2
[root@zorrozou-pc0 zorro]# nice
3
0

另外,使用renice命令可以對一個正在執行的程序進行nice值的調整,我們也可以使用比如top、ps等命令檢視程序的nice值,具體方法我就不多說了,大家可以參閱相關manpage。

需要大家注意的是,我在這裡都在使用nice值這一稱謂,而非優先順序priority這個說法。當然,nice和renice的man手冊中,也說的是priority這個概念,但是要強調一下,請大家真的不要混淆了系統中的這兩個概念,一個是nice值,一個是priority值,他們有著千絲萬縷的關係,但對於當前的Linux系統來說,它們並不是同一個概念。

我們看這個命令:

12345

大家是否真的明白其中PRI列和NI列的具體含義有什麼區別?同樣的,如果是top命令:

1
Tasks: 1587 total,   7 running, 1570 sleeping,   0 stopped,  10 zombie
2
Cpu(s): 13.0%us,  6.9%sy,  0.0%ni, 78.6%id,  0.0%wa,  0.0%hi,  1.5%si,  0.0%st
3
Mem:  132256952k total, 107483920k used, 24773032k free,  2264772k buffers
4
Swap:  2101192k total,      508k used,  2100684k free, 88594404k cached
5
6
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                                                                                                                                                          
7
 3001 root      20   0  232m  21m 4500 S 12.9  0.0   0:15.09 python                                                                                                                                                                                                                                                                                
8
11541 root      20   0 17456 2400  888 R  7.4  0.0   0:00.06 top     

大家是否搞清楚了這其中PR值和NI值的差別?如果沒有,那麼我們可以首先搞清楚什麼是nice值。

nice值雖然不是priority,但是它確實可以影響程序的優先順序。

在英語中,如果我們形容一個人nice,那一般說明這個人的人緣比較好。什麼樣的人人緣好?往往是謙讓、有禮貌的人。比如,你跟一個nice的人一起去吃午飯,點了兩個一樣的飯,先上了一份後,nice的那位一般都會說:“你先吃你先吃!”,這就是人緣好,這人nice!但是如果另一份上的很晚,那麼這位nice的人就要餓著了。這說明什麼?越nice的人搶佔資源的能力就越差,而越不nice的人搶佔能力就越強。這就是nice值大小的含義,nice值越低,說明程序越不nice,搶佔cpu的能力就越強,優先順序就越高。在原來使用O1排程的Linux上,我們還會把nice值叫做靜態優先順序,這也基本符合nice值的特點,就是當nice值設定好了之後,除非我們用renice去改它,否則它是不變的。而priority的值在之前核心的O1排程器上表現是會變化的,所以也叫做動態優先順序

優先順序和實時程序

簡單瞭解nice值的概念之後,我們再來看看什麼是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。新產生程序的預設優先順序被定義為:

1

實際上對應的就是nice值的0。正常情況下,任何一個程序的優先順序都是這個值,即使我們通過nice和renice命令調整了程序的優先順序,它的取值範圍也不會超出100-139的範圍,除非這個程序是一個實時程序,那麼它的優先順序取值才會變成0-99這個範圍中的一個。這裡隱含了一個資訊,就是說當前的Linux是一種已經支援實時程序的作業系統。

什麼是實時作業系統,我們就不再這裡詳細解釋其含義以及在工業領域的應用了,有興趣的可以參考一下實時作業系統的維基百科。簡單來說,實時作業系統需要保證相關的實時程序在較短的時間內響應,不會有較長的延時,並且要求最小的中斷延時和程序切換延時。對於這樣的需求,一般的程序排程演算法,無論是O1還是CFS都是無法滿足的,所以核心在設計的時候,將實時程序單獨映射了100個優先順序,這些優先順序都要高與正常程序的優先順序(nice值),而實時程序的排程演算法也不同,它們採用更簡單的排程演算法來減少排程開銷。總的來說,Linux系統中執行的程序可以分成兩類:

  1. 實時程序
  2. 非實時程序

它們的主要區別就是通過優先順序來區分的。所有優先順序值在0-99範圍內的,都是實時程序,所以這個優先順序範圍也可以叫做實時程序優先順序,而100-139範圍內的是非實時程序。在系統中可以使用chrt命令來檢視、設定一個程序的實時優先順序狀態。我們可以先來看一下chrt命令的使用:

1
[root@zorrozou-pc0 zorro]# chrt
2
Show or change the real-time scheduling attributes of a process.
3
4
Set policy:
5
 chrt [options] <priority> <command> [<arg>...]
6
 chrt [options] -p <priority> <pid>
7
8
Get policy:
9
 chrt [options] -p <pid>
10
11
Policy options:
12
 -b, --batch          set policy to SCHED_OTHER
13
 -f, --fifo           set policy to SCHED_FIFO
14
 -i, --idle           set policy to SCHED_IDLE
15
 -o, --other          set policy to SCHED_OTHER
16
 -r, --rr             set policy to SCHED_RR (default)
17
18
Scheduling flag: