最近在做一個項目,大概思路是
1.在一個進程中創建n個線程
2.每個線程中再啟動某一進程,當該進程執行完畢后,再次啟動該進程
難點在於對於需啟動的進程的監測:
實現思路是:檢測/proc/pid/stat目錄文件,只有當進程存在時才能夠打開該文件,文件中對進城的一些信息進行了基礎描述
遇到的問題為:長時間循環啟動進程總會出現進程“不運行”的情況,排查了很久發現是“僵屍進程“導致。此時/proc/pid/stat中的進程的狀態描述為“Z” 即表示僵屍進程,如下
解決方案:對於一般的父進程創建后可以直接使用wait或者waitpid進行子進程的回收,可是我使用的創建進程模式是分離式,即創建后父進程號為1(init進程),對於這種情況一方面是找到產生這種僵屍進程的原因進而避免,另外一個方面如果實在避免不了,那就需要進行判斷該進程到底何時成為僵屍進程,然后再根據自己的業務邏輯進行處理,比如說殺死該進程然后重新創建(一般這種僵屍進程只能將其父進程殺死后才能徹底將其清除)也可以直接忽略了該進程重新創建一個新的進程(由於這個時候的僵屍進程由init進程直接處理,所以不用擔心其不會回收)
在一篇博客中找到了產生這種進程的解釋
====================== 以下是原文 ======================
首先是 父進程為1號進程的進程 會不會成為僵屍進程??
---------------------------------------普通進程------------------------------------------
普通進程,父進程不主動去回收子進程的資源。
一個子進程在其父進程還沒有調用wait()或waitpid()的情況下退出。這個子進程就是僵屍進程。產生僵屍進程的原因:
1、子進程結束后向父進程發出SIGCHLD信號,父進程默認忽略了它;
2、父進程沒有調用wait()或waitpid()函數來等待子進程的結束;
處理辦法:把父進程殺掉,僵屍進程會變成孤兒進程,然后過繼給1號進程,而1號進程會掃描名下子進程,把 Z 狀態進程回收;
這時候僵屍進程已經退出了,只保留了task_struct結構體,所以發信號(-9等信號)去處理僵屍進程是無效的;
-----------------------------------ppid=1的進程-------------------------------
通過對普通僵屍進程的分析,這樣看起來好像 父進程為1號進程的進程 不會成為僵屍進程了,因為1號進程都會時刻掃描其子進程的狀態。
發現是 僵屍進程就會馬上去釋放它的資源;
但是,父進程為1號進程的進程 其實也是有可能成為僵屍進程的。下面說幾種情況:
1、進程還在被其它進程使用,退出;
2、進程的子線程還在執行任務,但主線程已經死掉了(可能主線程已經被殺了,systemd停止服務時會發SIGTERM信號);
3、進程阻塞在某一IO請求上,這時控制權已交到內核手上,這時如果子進程被KILL掉, 那么就成為父進程ID為1的僵屍進程,這個進程不會退出,會一直阻塞直到IO請求被滿足;
那當出現父進程為1號進程的僵屍進程時,需要分析時,可以考慮上面幾種情況;
1、查看下當前這個僵屍進程是否被其他進程使用,比如:被跟蹤,調試之類的;
2、用ps -T -p 查看下這個僵屍進程的主線程是否退出;
3、用strace 跟蹤下這個僵屍進程看看是否有io在等待,或者查看下載僵屍之前是否有io類的操作發生;
————————————————
原文鏈接:https://blog.csdn.net/KgdYsg/article/details/89503457