摘要:通過設定和改變進程的優先順序來讓進程獲得所需要的已耗用時間片段。
1 概述
本文講幫你在如下幾個方面打牢基礎:
- (1) 理解進程優先順序
- (2) 設定進程優先順序
- (3) 改變進程優先順序
本文為備考LPIC-1的目標103.6,權重為2。
2 理解你的優先順序
與其他大多數現代作業系統一樣,Linux也能運行多個進程。這通過進程間共用CPU和其他資源完成。如果一個進程佔用了100%的CPU,那麼其他進程將會失去反應。
如果你運行top命令,預設情況下,會按照CPU佔用率降序顯示各個進程。前面的例子中,我們展示了一個Poor Man's Colck指令碼,它每30秒列印一次目前時間,其它時間內則沒有動作。top可能不會把這個進程顯示出來,因為它大部分時間都沒有使用CPU。
典型的top輸出:
Mem: 3924872k total, 3429320k used, 495552k free, 529468k buffersSwap: 7574520k total, 0k used, 7574520k free, 1872160k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1580 mysql 20 0 870m 73m 6748 S 0.3 1.9 100:09.57 mysqld14163 root 20 0 15024 1384 1008 R 0.3 0.0 0:00.06 top 1 root 20 0 19228 1532 1248 S 0.0 0.0 0:11.62 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root RT 0 0 0 0 S 0.0 0.0 0:08.19 migration/0 4 root 20 0 0 0 0 S 0.0 0.0 0:10.33 ksoftirqd/0 5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0 6 root RT 0 0 0 0 S 0.0 0.0 0:18.44 watchdog/0 7 root RT 0 0 0 0 S 0.0 0.0 0:08.87 migration/1 8 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/1 9 root 20 0 0 0 0 S 0.0 0.0 0:14.39 ksoftirqd/1 10 root RT 0 0 0 0 S 0.0 0.0 0:18.44 watchdog/1 11 root RT 0 0 0 0 S 0.0 0.0 0:07.99 migration/2 12 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/2 13 root 20 0 0 0 0 S 0.0 0.0 0:14.89 ksoftirqd/2 14 root RT 0 0 0 0 S 0.0 0.0 0:17.60 watchdog/2 15 root RT 0 0 0 0 S 0.0 0.0 0:06.82 migration/3 16 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/3 17 root 20 0 0 0 0 S 0.0 0.0 0:05.61 ksoftirqd/3 18 root RT 0 0 0 0 S 0.0 0.0 0:17.79 watchdog/3 19 root 20 0 0 0 0 S 0.0 0.0 6:35.02 events/0 20 root 20 0 0 0 0 S 0.0 0.0 6:39.81 events/1 21 root 20 0 0 0 0 S 0.0 0.0 70:32.21 events/2 22 root 20 0 0 0 0 S 0.0 0.0 8:35.72 events/3 23 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cgroup 24 root 20 0 0 0 0 S 0.0 0.0 0:00.00 khelper 25 root 20 0 0 0 0 S 0.0 0.0 0:00.00 netns 26 root 20 0 0 0 0 S 0.0 0.0 0:00.00 async/mgr 27 root 20 0 0 0 0 S 0.0 0.0 0:00.00 pm 28 root 20 0 0 0 0 S 0.0 0.0 0:45.88 sync_supers 29 root 20 0 0 0 0 S 0.0 0.0 0:53.20 bdi-default 30 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kintegrityd/0 31 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kintegrityd/1
你的系統中可能會有一些進程使用很多的CPU資源,如視頻編輯工具、圖片格式轉換工具或音頻格式轉換工具,如mp3轉為ogg。
當你的機器上只有一個或者有限個數的CPU時,你需要決定如何在多個競爭進程之間共用CPU資源。這通常是通過選中一個進程讓它運行一段時間(時間片),或者讓它停止運行直到它等待的事件如IO完成。為了確保重要的進程不會因為CPU資源缺乏而失去反應,這種選擇是基於調度優先順序的。上表中的NI列代表的是進程的調度優先順序,也叫做niceness。優先順序通常是在-20到19之間,其中-20代表最高優先順序,19代表最低優先順序。
2.1 使用ps查看優先順序
除了top命令外,也可以使用ps命令來顯示進程優先順序。使用ps -l,其輸出的NI列就是進程優先順序。如下所示:
[root@centos192 ~]# ps -lF S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD4 S 0 14148 14146 0 80 0 - 27074 wait pts/1 00:00:00 bash4 R 0 14548 14148 0 80 0 - 27030 - pts/1 00:00:00 ps
2.2 預設優先順序
你能已經從上面的兩個例子中猜出來了,至少由普通使用者啟動的進程的優先順序是0。這對現在的Linux系統來說是正確的。這個預設值可以通過運行不帶參數的nice命令來擷取。
ot@centos192 ~]# nice0
3 設定優先權
在我們學習如何設定和改變優先順序之前,先構建一個CPU密集型的指令碼,它將會展示優先順序確實有影響。
3.1 一個CPU密集型的指令碼
我們將建立一個只使用CPU的小指令碼。這個指令碼使用兩個輸入參數,一個是計數值,一個是標籤。首先會列印出這個標籤和當前的系統時間,然後進入迴圈,每次迴圈都使得計數值減一,當計數值為0時終止迴圈,列印出標籤和時間。這個測試指令碼中沒有進行錯誤偵測也不是非常健壯,但是它可以說明問題了。
[root@centos192 ~]# echo 'x="$1"' > count1.sh[root@centos192 ~]# echo 'echo "$2" $(date)' >> count1.sh[root@centos192 ~]# echo 'while [ $x -gt 0 ]; do x=$((x-1)); done' >>count1.sh[root@centos192 ~]# echo 'echo "$2" $(date)' >>count1.sh[root@centos192 ~]# cat count1.shx="$1"echo "$2" $(date)while [ $x -gt 0 ]; do x=$((x-1)); doneecho "$2" $(date)
如果你在電腦上運行這個指令碼,可能的輸出如下:
[root@centos192 ~]# ./count1.sh 10000 AA 2013年 08月 09日 星期五 10:30:28 CSTA 2013年 08月 09日 星期五 10:30:28 CST[root@centos192 ~]# ./count1.sh 99000 AA 2013年 08月 09日 星期五 10:30:43 CSTA 2013年 08月 09日 星期五 10:30:45 CST
目前位置一切安好。現在我們在後台運行這個指令碼,然後使用top命令來查看其CPU佔有情況。
Tasks: 188 total, 2 running, 186 sleeping, 0 stopped, 0 zombieCpu(s): 23.8%us, 1.2%sy, 0.0%ni, 74.8%id, 0.1%wa, 0.0%hi, 0.0%si, 0.0%stMem: 3924872k total, 3438424k used, 486448k free, 529588k buffersSwap: 7574520k total, 0k used, 7574520k free, 1873432k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND29561 root 20 0 105m 1096 728 R 99.6 0.0 1:06.54 bash 695 root 20 0 0 0 0 S 0.3 0.0 4:35.89 vmmemctl29562 root 20 0 15024 1388 1008 R 0.3 0.0 0:00.13 top 1 root 20 0 19228 1532 1248 S 0.0 0.0 0:11.67 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
可以看出,我們的指令碼使用了一個CPU的99.6的資源,如果想佔用其他的CPU,則再運行上面的命令即可。如果指令碼持續運行,那麼將會嚴重影響系統的其他工作。
3.2 使用nice命令設定優先權
既然我們能夠持續保持一個CPU處於繁忙狀態,我們來看看如何設定一個進程的優先順序。總結一下到目前為止我們學到的知識:
- (1) Linux和Unix系統使用的優先順序共有40個等級,從-20到+19.
- (2) 普通使用者啟動的進程預設優先順序是0.
- (3) ps命令的-l選項可以顯示進程的優先順序
- (4) nice命令來顯示預設的優先順序
nice除了可以顯示預設優先順序外,還可以用來按照指定的優先順序啟動一個進程。你可以使用-n(或者--adjustment)選項接一個正數來增加優先順序值,接一個負數來減少優先順序值。一定要記住優先順序值越大,優先順序越低。通常只有root使用者才能指定負值,也就是說普通使用者只能讓進程優先順序降低而不能提升。
為了示範使用nice設定優先權,我們使用相同的指令碼啟動兩個進程,其中一個進程的優先順序為19,另一個預設。一秒以後使用ps-l 來顯示進程狀態,包括優先順序。最後我們增加了一個30秒的睡眠來保證在子sh運行完之後才退出命令。如所示:
[root@centos192 ~]# (sh count1.sh 2000000 A&);(nice -n 19 sh count1.sh 2000000B&);sleep 1; ps -l; sleep 30A 2013年 08月 09日 星期五 12:29:10 CSTB 2013年 08月 09日 星期五 12:29:10 CSTF S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD4 S 0 29538 29536 0 80 0 - 27074 wait pts/2 00:00:00 bash0 R 0 30573 1 99 80 0 - 26514 - pts/2 00:00:01 sh0 R 0 30575 1 99 99 19 - 26514 - pts/2 00:00:00 sh4 R 0 30579 29538 0 80 0 - 27030 - pts/2 00:00:00 psB 2013年 08月 09日 星期五 12:29:39 CSTA 2013年 08月 09日 星期五 12:29:40 CST
可能你會感到奇怪,這兩個子進程幾乎同時運行完畢。我們設定的優先順序沒有作用嗎?請記住我們的指令碼只使用一個CPU。此次啟動並執行機器配備的是4核心的CPU。這樣兩2個子進程分別運行在不同的CPU核心上,也許沒有必要讓誰優先了。為了佔滿4個CPU核心,我們這次同時運行6個進程,優先順序分別是0,4,8,12,16,19。
[root@centos192 ~]# (sh count1.sh 5000000 A&);(nice -n 4 sh count1.sh 5000000B&);(nice -n 8 sh count1.sh 5000000 C&);(nice -n 12 sh count1.sh 5000000D&);(nice -n 16 sh count1.sh 5000000 E&);(nice -n 19 sh count1.sh 5000000F&);sleep 1; ps -l; sleep 30; A 2013年 08月 09日 星期五 12:25:05 CSTB 2013年 08月 09日 星期五 12:25:05 CSTC 2013年 08月 09日 星期五 12:25:05 CSTD 2013年 08月 09日 星期五 12:25:05 CSTE 2013年 08月 09日 星期五 12:25:05 CSTF 2013年 08月 09日 星期五 12:25:05 CSTF S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD4 S 0 29538 29536 0 80 0 - 27074 wait pts/2 00:00:00 bash0 R 0 30471 1 50 80 0 - 26514 - pts/2 00:00:01 sh0 R 0 30473 1 50 84 4 - 26514 - pts/2 00:00:01 sh0 R 0 30475 1 49 88 8 - 26514 - pts/2 00:00:00 sh0 R 0 30477 1 30 92 12 - 26514 - pts/2 00:00:00 sh0 R 0 30480 1 12 96 16 - 26514 - pts/2 00:00:00 sh0 R 0 30484 1 6 99 19 - 26514 - pts/2 00:00:00 sh4 R 0 30489 29538 0 80 0 - 27029 - pts/2 00:00:00 psC 2013年 08月 09日 星期五 12:26:19 CSTA 2013年 08月 09日 星期五 12:26:19 CSTB 2013年 08月 09日 星期五 12:26:20 CSTD 2013年 08月 09日 星期五 12:26:49 CSTE 2013年 08月 09日 星期五 12:27:15 CSTF 2013年 08月 09日 星期五 12:27:25 CST
可以看出,如此一來就會出現多個進程使用競爭CPU的情況了,基本上優先順序越高,那麼被執行的機會就越多,執行完畢使用的時間就越少。
最後提醒大家,如同nohup命令一樣,nice命令不能使用命令列表或者管線作為參數。
4 改變優先順序4.1 renice
如果你已經啟動了一個進程,之後又意識到需要改變這個進程的優先順序,那麼就可以使用renice命令。renice指定的是絕對優先順序值而不是調整量。
i[root@centos192 ~]# sh count1.sh 10000000 A&[1] 30799[root@centos192 ~]# A 2013年 08月 09日 星期五 12:43:19 CST[root@centos192 ~]# renice 1 30799; ps -l 3079930799: old priority 0, new priority 1F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD0 R 0 30799 29538 97 81 1 - 26514 - pts/2 0:21 sh count1.sh10000000 A[root@centos192 ~]# renice +3 30799; ps -l 3079930799: old priority 1, new priority 3F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD0 R 0 30799 29538 98 83 3 - 26514 - pts/2 0:40 sh count1.sh10000000 A
注意,只有root使用者才能提高進程的調度優先順序,讓進程變得不太nice。更多資訊參考nice和renice的man手冊頁。