>>> 此貼的回復 >> 淺議Unix的defunct進程(“僵屍”進程) 本文出自:http://www2.ccw.com.cn 作者: 張道新 趙國明 (2002-04-17 08:02:00) 在Unix系統管理中,當用ps命令觀察進程的執行狀態時,經常看到某些進程的狀態欄為defunct,這就是所謂的“僵屍”進程。“僵屍”進程是一個早已死亡的進程,但在進程表(processs table)中仍占了一個位置(slot)。由於進程表的容量是有限的,所以,defunct進程不僅占用系統的內存資源,影響系統的性能,而且如果其數目太多,還會導致系統癱瘓。
我們知道,每個Unix進程在進程表裡都有一個進入點(entry),核心程序執行該進程時使用到的一切信息都存儲在進入點。當用ps命令察看系統中的進程信息時,看到的就是進程表中的相關數據。當以fork()系統調用建立一個新的進程後,核心進程就會在進程表中給這個新進程分配一個進入點,然後將相關信息存儲在該進入點所對應的進程表內。這些信息中有一項是其父進程的識別碼。當這個進程走完了自己的生命周期後,它會執行exit()系統調用,此時原來進程表中的數據會被該進程的退出碼(exit code)、執行時所用的CPU時間等數據所取代,這些數據會一直保留到系統將它傳遞給它的父進程為止。由此可見,defunct進程的出現時間是在子進程終止後,但是父進程尚未讀取這些數據之前。利用這一點我們可以用下面的程序建立一個defunct 進程:
#include ;
#include;
main(){
if(!fork()){
printf(“child pid=%d\n”, getpid());
exit(0)
}
sleep(20);
printf(“parent pid=%d \n”, getpid());
exit(0);
}
當上述程序以後台的方式執行時,第8行強迫程序睡眠20秒,讓用戶有時間輸入ps -e指令,觀察進程的狀態。當父進程執行終止後,再用ps -e命令觀察時,我們會發現defunct進程也隨之消失。這是因為父進程終止後,init 進程會接管父進程留下的這些“孤兒進程”(orphan process),而這些“孤兒進程”執行完後,它在進程表中的進入點將被刪除。如果一個程序設計上有缺陷,就可能導致某個進程的父進程一直處於睡眠狀態或是陷入死循環,那麼當該子進程執行結束後就變成了defunct進程,這個defunct 進程可能會一直留在系統中直到系統重新啟動。
如果我們將上述程序略作修改,在第8行sleep()系統調用前執行wait()或waitpid()系統調用,則子進程在終止後會立即把它在進程表中的數據返回給父進程,此時系統會立即刪除該進入點。在這種情形下就不會產生defunct進程。
由於調度程序無法選中Defunct 進程,所以不能用kill命令刪除Defunct 進程,惟一的方法只有重啟系統
>>> 此貼的回復 >> 不知道你的服務器是什麼?apache?
如果父進程不等待子進程結束,子進程以後將成為僵屍進程,就是zombie。如果父進程等待子進程結束,將增加父進程的負擔,影響服務器進程的並發性能。 在Linux下通過將SIGCHLD信號的操作設為SIG_IGN。 sgnal(SIGCHLD,SIG_IGN); 這樣,內核在子進程結束時不會產生僵屍進程。 在上BSD下好像必須顯式等待子進程結束以後才能釋放僵屍進程。
但是都可以通過父進程fork兩次的方法避免僵屍進程