原創:打碼日記(微信公眾號ID:codelogs),歡迎分享,轉載請保留出處。
簡介
這是Linux命令拾遺系列的第八篇,本篇主要介紹top命令中nice%這個指標的含義以及進程優先級相關內容。
本系列文章索引
Linux命令拾遺-入門篇
Linux命令拾遺-文本處理篇
Linux命令拾遺-軟件資源觀測
Linux命令拾遺-硬件資源觀測
Linux命令拾遺-剖析工具
Linux命令拾遺-動態追蹤工具
Linux命令拾遺-理解系統負載
在各種查看CPU使用率的工具中(如top),一般都有us%、sy%、ni%等,us%與sy%含義是比較容易理解的,一個是用戶態CPU使用率,一個是內核態CPU使用率。
但ni%就比較晦澀難懂了,它代表被調整過nice值的進程占用的CPU使用率,很難理解對不對,來看看下面的例子。
調整進程nice值
首先,我們使用stress命令起2個進程,對CPU制造一些壓力,如下:
# 起2個吃CPU的后台進程
$ stress -c 2 &
# 查看兩個stress進程,進程號為194022、194022
$ pstree -Tp $$
bash(193921)─┬─pstree(194101)
└─stress(194017)─┬─stress(194022)
└─stress(194023)
由於我機器是多核的,操作系統會將兩個stress進程調度到兩個核上,為了達到效果,我們將這2個進程綁定到1號核上運行,如下:
# 綁定2個stress進程到CPU的1號核上
$ taskset -pc 1 194022
$ taskset -pc 1 194023
# 然后使用top查看,如下圖
$ top
可以看到,此時%Cpu1是占滿的100%,兩個stress進程各占50%,這很好理解,兩個同樣吃CPU進程跑在一個核上,大家各分一半嘛!
這里需要注意一下進程的PR與NI列,這兩個都代表了進程的優先級,PR是內核調度時使用的優先級(priority),默認20,值越大優先級越低,而NI是開放給用戶調整的優先級(nice),默認0,nice值越大,則進程會表現得越謙讓(nice),先讓別的進程獲得CPU,表現為優先級越低。
如下,我們通過renice命令調整194023進程的nice值為5,以降低它的優先級:
$ renice -n 5 -p 194023
$ top
可以發現,現在%Cpu1的us是75.7,ni是24.3,沒被調整nice的進程194022的%CPU是75.1,而調整了的進程194023的%CPU是24.6,同時NI列從0變成了5,PR列從20變成了25,可以發現%ni的值24.3幾乎等於被調整過nice值進程的CPU使用率,即24.6。
再看看我開頭說的ni%的定義,ni%代表被調整過nice值的進程占用的CPU使用率
,現在感覺這句話是不是再清楚不過了,被調整了nice值的進程,會從us%中分離出來單獨顯示,這樣當一批非常吃CPU的進程被調整nice值后,調整的人就能非常清楚的知道,這些進程現在占用多少CPU了。
如下,再通過renice命令調用194023進程的nice值為19,這是nice值能設置的最大值:
$ renice -n 19 -p 194023
$ top
可以發現194023這個進程CPU使用率更低了,且%Cpu1的ni也更低了,並且NI變成了19,PR變成了39。
PR與NI
上面可以看到,PR與NI好像滿足這樣一種等式關系:PR = 20 + NI
,那么為什么Linux要設計這兩套優化級呢?
其實,在進程執行的過程中,就算你調整了進程NI值導致PR變化,PR還是可以再次由CPU調度器根據需要動態調整的,在這種情況下,上面的公式就不成立了。並且,在內核代碼里,PR才是CPU調度器真正使用的優化級,而NI只是開放給用戶修改的。
另外,NI值是給普通進程使用的,范圍是[-20 ~ 19]
共39個級別,對應PR就是[0 ~ 39]
。
而PR的取值范圍可以是[-100 ~ 39]
共139個級別,其中[-100, -1]
是給實時進程用的。
所以在Linux中PR大於0是普通進程,小於0是實時進程。
注:在top中會看到 PR = rt 的進程,這個rt等同於-100
可以發現,對於普通進程,不管用戶怎么調整NI值,進程的PR都不會低於0,也就是保證所有實時進程的優先級,都要大於普通進程,像Linux中的一些內核進程就是實時進程(如:migration/0),必須保證他們被優先執行。
如下,在Linux中,可以通過chrt命令查看內核支持的實時進程調度策略:
$ chrt -m
SCHED_OTHER min/max priority : 0/0
SCHED_FIFO min/max priority : 1/99
SCHED_RR min/max priority : 1/99
SCHED_BATCH min/max priority : 0/0
SCHED_IDLE min/max priority : 0/0
SCHED_DEADLINE min/max priority : 0/0
是的,你會發現SCHED_FIFO/SCHED_RR策略都有[1,99]
共99個實時優先級(real_time_priority)可用,它和PR的關系是:PR = -1 - real_time_priority
。
如下,之前通過增大NI值而降低了優先級的194023進程,我再把它修改為實時進程:
# 設置194023進程為實時進程,調度策略為SCHED_RR,實時優先級為10,PR = -1 -10 = -11
$ sudo chrt --rr --pid 10 194023
# 查看實時優先級
$ chrt -p 194023
pid 194023's current scheduling policy: SCHED_RR
pid 194023's current scheduling priority: 10
# 再看CPU使用率
$ top
可以看到,194023被調整為實時進程后,把CPU占滿了,沒有給同核心運行的普通進程194022留下任何CPU時間。
所以實時進程的調度是搶占式的,只要其不結束,低優先級進程完全沒有機會使用CPU,而對於普通進程而言,多少會留一點CPU時間給其它低優先級的普通進程使用的。
另外,使用ps -l
也可以查看進程的PR與NI,如下:
$ ps -lp 194022 194023
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
1 R 0 194022 194017 97 80 0 - 964 - ? 1943:32 stress -c 2
1 R 0 194023 194017 2 49 - - 964 - ? 52:08 stress -c 2
看PRI這一列,可以發現,194022在top中是20,在ps中是80,而194023在top中是-11,在ps中是49,它們都相差60。
是的,他們含義是一致的,只是顯示的基准值不同而已,top中0以下代表實時進程,而ps -l
中60以下代表實時進程。
往期內容
Linux命令拾遺-入門篇
原來awk真是神器啊
Linux文本命令技巧(上)
Linux文本命令技巧(下)
字符編碼解惑