一、進程的狀態
1、命令查看
top PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 28961 root 20 0 43816 3148 4040 R 3.2 0.0 0:00.01 top 620 root 20 0 37280 33676 908 D 0.3 0.4 0:00.01 app 1 root 20 0 160072 9416 6752 S 0.0 0.1 0:37.64 systemd 1896 root 20 0 0 0 0 Z 0.0 0.0 0:00.00 devapp 2 root 20 0 0 0 0 S 0.0 0.0 0:00.10 kthreadd 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H 6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq 7 root 20 0 0 0 0 S 0.0 0.0 0:06.37 ksoftirqd/0
2、進程狀態圖解
向一個進程發送SIGSTOP 信號,它就會因響應這個信號變成暫停狀態(Stopped);再向它發送 SIGCONT 信號,進程又會恢復運行(如果進程是終端里直接起動的,
則需要你用fg命令,回復到前台運行)
而當你的用的調試器調試一個進程是,在使用斷點中斷進程后,進程就會變成跟蹤狀態,這其實也就是一種特殊的暫停狀態,只不過你可以用調試器
來跟蹤並按需控制進程的運行
了解了這些,我們再回到今天的主題,先看不可終端狀態,這其實是為了保證進程數據與硬件狀態一直,並且增長情況下,不可終端狀態在很短時間內會結束,
所以短時的不可終端進程我們一般可忽略
但如果系統或硬件發生了故障,進程可能會在不可中斷狀態保持很久,甚至導致系統中出現大量不可中斷進程,這時,你就得注意下,系統時不時出現了I/O 等性能問題。
再看僵屍進程,這是多進程應用很容易碰到的問題,正常情況下,當一個進程創建了子進程后,它應該通過系統調用 wait() 或者 waitpid() 等待子進程結束,回收子進程的資源;
而子進程在結束時,會向它的父進程發送SIGCHLD 信號,所以,父進程還可以注冊 SIGCHLD信號的處理函數,異步回收資源
如果父進程這么做,或是子進程執行太快,父進程還沒有來得及處理子進程狀態,子進程就已經提前退出,那這時的紫禁城就會變成僵屍進程,換句話說,父親應該一直對兒子負責,善始善終,如果不作為或者跟不上、都會導致"問題少年"的出現
通常、僵屍進程持續的時間都比較短,在父進程回收它的資源后就會消亡;或者在父進程推出后,由init進程回收后也會消亡
一旦父進程沒有處理子進程的種植,還一直保持運行狀態,那么子進程就會一直處於僵屍狀態,大量的僵屍進程會用盡PID進程號,
導致新進程不能創建,所以這種情況一定要避免
二、案例分析
1、運行案例應用
docker run --privileged --name=app -itd feisky/app:iowait
2、ps命令確認案例應用已正常啟動
ps aux | grep /app root 4009 0.0 0.0 4376 1008 pts/0 Ss+ 05:51 0:00 /app root 4287 0.6 0.4 37280 33660 pts/0 D+ 05:54 0:00 /app root 4288 0.6 0.4 37280 33668 pts/0 D+ 05:54 0:00 /app
1、s 和 + 是什么意思呢?
s 表示這個進程是一個會話的領導進程,而 + 表示前台進程組
這里又出現了兩個新概念,進程組和會話,他們用來管理一組相互關聯的進程,意思其實很好理解
2、什么是進程組?
進程組表示一組相互關聯的進程,比如每個子進程都是父進程所在組的成員;而會話是只共享同一個控制終端的一個或多個進程組
3、什么是會話?
比如,我么通過SSH登錄服務器,就會打開一個控制終端(TTY),這個控制終端就對應一個會話,而我我們在終端中運行的命令以及他們的子進程
就構成了一個個的進程組,其中,在后台運行的命令,構成后台進程組;在前台運行的命令,就構成前台進程組
3、top查看資源使用情況
# 按下數字 1 切換到所有 CPU 的使用情況,觀察一會兒按 Ctrl+C 結束 $ top top - 05:56:23 up 17 days, 16:45, 2 users, load average: 2.00, 1.68, 1.39 Tasks: 247 total, 1 running, 79 sleeping, 0 stopped, 115 zombie %Cpu0 : 0.0 us, 0.7 sy, 0.0 ni, 38.9 id, 60.5 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.0 us, 0.7 sy, 0.0 ni, 4.7 id, 94.6 wa, 0.0 hi, 0.0 si, 0.0 st ... PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4340 root 20 0 44676 4048 3432 R 0.3 0.0 0:00.05 top 4345 root 20 0 37280 33624 860 D 0.3 0.0 0:00.01 app 4344 root 20 0 37280 33624 860 D 0.3 0.4 0:00.01 app 1 root 20 0 160072 9416 6752 S 0.0 0.1 0:38.59 systemd ...
4、分析過程
從這里你能看出什么問題嗎?逐行觀察,別放過任何一個地方,忘了哪行參數意思的話,也要及時返回去復習
先看第一行平均負載,過去1、5、15分鍾內的平均負載依次減小,說明平均負載正在升高,而1分鍾內的平均負載已經達到了系統CPU的個數,說明系統可能已經有了性能瓶頸
Tasks 有1個正在運行的進程,但僵屍進程比較多,而且還在不停增加,說明有子進程在退出時沒有沒清理
CPU使用率:用戶CPU和系統CPU都不高,但iowait分別是60.5%和94.6%好像有點不正常
每個進程的情況:CPU使用率最高的進程只有0.3%,看起來並不高;但是有兩個進程處於D狀態,它們可能在等待I/O,但光憑這里並不能確定是它們導致了 iowait 升高
我們把這四個問題在匯總一下,就可以得到很明確的兩點:
第一點:iowait太高了,導致系統的平均負載生該,甚至達到系統CPU的個數
第二點:僵屍進程在不斷增多,說明程序沒能正確清理子進程的資源
三、遇到的問題及小結
1、用top命令觀察,平均負載也不高,然后wa也很低,也沒有看到D狀態的進程
2、解決辦法
老師說可能是案例里I/O線程還不夠多,效果不明顯,等着老師修改案例重新發鏡像,再實驗。
在和老師多次交流下,終於逼得老師發布一個把自己機器跑死的鏡像,就可以了,結果和老師的溫和了。
[root@luoahong ~]# docker run --privileged --name=app -itd feisky/app:iowait-new2 Unable to find image 'feisky/app:iowait-new2' locally iowait-new2: Pulling from feisky/app 32802c0cfa4d: Already exists da1315cffa03: Already exists fa83472a3562: Already exists f85999a86bef: Already exists f69cb5280862: Pull complete Digest: sha256:9fc8b013aff0bc2c1b1dc41a33989a8ddd4ed7da56f53f6559bbc76836041dc2 Status: Downloaded newer image for feisky/app:iowait-new2 00ed5564248127a98c467eb99f8b32d3dc3ebc5d7f47563d6617ccfd7348b10b [root@luoahong ~]# ps aux | grep /app root 11798 0.1 0.0 4368 380 pts/0 Ss+ 09:54 0:00 /app root 11851 0.0 0.8 70040 65776 pts/0 R+ 09:55 0:00 /app root 11852 0.0 0.8 70040 65776 pts/0 R+ 09:55 0:00 /app root 11854 0.0 0.0 112708 980 pts/0 S+ 09:55 0:00 grep --color=auto /app
top截圖
執行這個鏡像,iowait打滿,直接把我的微信給擠掉了,瀏覽器都打不開了,不過結果是好的。
3、小結
用我么最熟悉的ps或者top,可以直接查看進程的狀態,這些狀態包括運行(R)、空閑(I)、不可中斷睡眠(D)、可中斷睡眠(S)、僵屍(Z)以及暫停(T)等
其中,不可中斷狀態和僵屍狀態,是我們今天學習的重點
不可中斷狀態:表示進程正在跟硬件交互,為了保護進程數據和硬件的一致性,系統不允許其他進程或中斷打斷這個進程。進程長時間處於不可中斷狀態,通常標識系統有I/O 性能問題
僵屍進程表示進程已經退出,但它的父進程還沒有回收子進程占用資源。短暫的僵屍狀態我們通常不必理會,但進程長時間屬於僵屍狀態,
就應該注意了,可能有應用程序沒有正常處理子進程退出