linux 性能自我學習 ———— 不可中斷進程和僵尸進程 [四]
前言
簡單介紹一下不可中斷進程和僵尸進程。
正文
先來看下進程的狀態:
那么這一列的狀態是什么呢?
R 是Running 或 Runnable 的縮寫, 表示進程在cpu 的就緒隊列中,正在運行或者正在等待運行。
D 是disk sleep 的縮寫,也就是不可中斷睡眠,一般表示進程正在跟硬件交互,并且交互過程不允許其他進程或者中斷打斷。
Z 是Zombie 的縮寫,表示僵尸進程,表示進程已經介紹了,但是父進程還沒有回收它的資源
S 是interruptible sleep 縮寫,也就是可中斷狀態睡眠,表示進程因為等待某個事件而被系統掛起。當進程等待的事件發生時, 他會被喚醒并進入R狀態
I 是 idle的縮寫, 也就是空閑狀態,用在不可中斷睡眠的內核線程上。前面說了,硬件交互導致不可中斷進程用D 表示,但是某些內核線程來說,他們可能實際并沒有任何負載,用idle 就是為了區分。
D 狀態的進程會導致平均負載升高,i 狀態的進程不會。
還有兩種狀態,一種是T 狀態,另外一種是X狀態。
X 是狀態為死亡,一般看不到。
另外一種是T 狀態,表示是stopped 或者 traced 狀態。
比如我們進程調試就是T狀態,發送一個信號sigstop,然后就會停止。再發送sigcont 信號,這個時候就會繼續運行。
該篇的主題是不可中斷進程和僵尸進程。
前面結束了,不可中斷進程,一般是在進行系統調用。
僵尸進程是怎么樣的呢? 僵尸進程在多進程中可能遇到。
正常情況下,當用給進程創建了子進程后,它應該通過系統調用wait() 或者 waitpid() 等待子進程結束,回收子進程資源。
而子進程結束時候,會向父進程發送sigchld信號,所以父進程還可以注冊sigchld 信號的畜欄里函數,異步回收資源。
如果父進程沒有那么做,或者子進程執行太快。父進程還沒來得及處理子進程狀態,那么子進程就已經提前推出,那么這個時候子進程就會變成僵尸進程。
通常,僵尸進程持續時間很短,如果父進程一直沒有處理子進程的終止,那么就會一直保持運行狀態,這個時候就會占用pid 進程號,導致新的進程不能創建。
實驗
docker run --privileged --name=app -itd feisky/app:iowait
top 一下:
僵尸進程特別多。
然后我們還發現了,Ss+ 和D+
這個+ 是什么意思呢?
有兩個概念。
進程組表示一組相互關聯的進程,比如每個子進程都是父進程所在組的成員
會話指共享一個控制終端的一個或者多個進程組。
那么這個時候,我們如何來分析呢?
yum install dstat
當iowait 升高時候,read 會很大,說明iowait 升高跟磁盤的讀請求相關,可能是磁盤讀導致的。
那么可以使用top 命令,觀察d狀態的進程。
然后通過pidstat
pidstat -d -p 4344 1 3
發現其并不高。
那么直接用pidstat 查看全部的:
pdistat -d 1 20
發現的確是app導致的。
然后就可以用strace 追蹤代碼了。
strace -p 6082
這種情況如果是root 用戶查看不了的話,那么可能這個進程不存在或者已經Z狀態了。
那么這個時候可以使用perf來搞定。
這個時候你就的確發現其在系統讀取了。
那么僵尸進程怎么解決呢?
前面已經發現了僵尸進程了。
那么可以找到其父進程:
pstree -aps 3084
可以看到程序還是app進程了。
然后就可以去檢查代碼部分了。
結
下一節linux 軟中斷。