僵尸行程是指一個已經終止、但是其父行程尚未對其進行善后處理獲取終止行程的有關資訊的行程,這個行程被稱為“僵尸行程”(zombie),
怎樣產生僵尸行程
一個行程在呼叫exit命令結束自己的生命的時候,其實它并沒有真正的被銷毀,而是留下一個稱為僵尸行程(Zombie)的資料結構(系統呼叫exit, 它的作用是使行程退出,但也僅僅限于將一個正常的行程變成一個僵尸行程,并不能將其完全銷毀),
在Linux行程的狀態中,僵尸行程是非常特殊的一種,它已經放棄了幾乎所有記憶體空間,沒有任何可執行代碼,也不能被調度,僅僅在行程串列中保留一個位 置,記載該行程的退出狀態等資訊供其他行程收集,除此之外,僵尸行程不再占有任何記憶體空間,它需要它的父行程來為它收尸,如果他的父行程沒安裝 SIGCHLD 信號處理函式呼叫wait或waitpid()等待子行程結束,又沒有顯式忽略該信號,那么它就一直保持僵尸狀態,如果這時父行程結束了, 那么init行程自動會接手這個子行程,為它收尸,它還是能被清除的,但是如果如果父行程是一個回圈,不會結束,那么子行程就會一直保持僵尸狀態,這就是 為什么系統中有時會有很多的僵尸行程,
怎么查看僵尸行程
利用命令ps,可以看到有父行程ID為1的行程是孤兒行程;s(state)狀態為Z的是僵尸行程,
注意:孤兒行程(orphan process)是尚未終止但已停止(相當于前臺掛起)的行程,但其父行程已經終止,由init收養;而僵尸行程則是已終止的行程,其父行程不一定終止,
怎樣來清除僵尸行程
- 改寫父行程,在子行程死后要為它收尸,具體做法是接管SIGCHLD信號,子行程死后, 會發送SIGCHLD信號給父行程,父行程收到此信號后,執行 waitpid()函式為子行程收尸,這是基于這樣的原理:就算父行程沒有呼叫wait,內核也會向它發送SIGCHLD訊息,盡管對的默認處理是忽略, 如果想回應這個訊息,可以設定一個處理函式,
- 把父行程殺掉,父行程死后,僵尸行程成為"孤兒行程",過繼給1號行程init,init始侄訓負責清理僵尸行程,關機或重啟后所有僵尸行程都會消失,
避免Zombie Process的方法
- 在SVR4中,如果呼叫signal或sigset將SIGCHLD的配置設定為忽略,則不會產生僵死子行程,另外,使用SVR4版的 sigaction,則可設定SA_NOCLDWAIT標志以避免子行程僵死, Linux中也可使用這個,在一個程式的開始呼叫這個函式signal(SIGCHLD,SIG_IGN),
- 呼叫fork兩次,
- 用waitpid等待子行程回傳,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/201272.html
標籤:其他
