Posted on 2009-04-14 15:28
Prayer 閱讀(979)
評論(0) 編輯 收藏 引用 所屬分類:
LINUX/UNIX/AIX
1. 僵死進程
當(dāng)一個程序創(chuàng)建的子進程比父進程提前結(jié)束,內(nèi)核仍然保存一些它的信息以便父進程會需要它 - 比如,父進程可能需要檢查子進程的退出狀態(tài)。為了得到這些
信息,父進程調(diào)用‘wait()’;當(dāng)這個調(diào)用發(fā)生,內(nèi)核可以丟棄這些信息。
在子進程終止后到父進程調(diào)用‘wait()’前的時間里,子進程被稱為‘僵死進程’ (‘zombie’)。(如果你用‘ps’,這個子進程會有一個‘Z’出現(xiàn)在它的
狀態(tài)區(qū)里指出這點。)
也就是說,當(dāng)子進程調(diào)用 do_exit() 后,子進程就終止了,與次進程相關(guān)聯(lián)的所有資源都被釋放掉了(假設(shè)進程是這些資源的唯一使用者)。 進程不可
運行,并處于TASK_ZOMBIE狀態(tài)。它所占用的資源就是內(nèi)核棧,thread_info結(jié)構(gòu)和task_struct結(jié)構(gòu)。此時進程存在的唯一目的就是向它的
父進程提供信息(子進程的退出代碼,也就是exit()提供的,存儲在task_struct中的exit_code成員)。父進程檢索到信息后(通過wait()系統(tǒng)調(diào)用),
或者通知內(nèi)核那是無關(guān)的信息后(在某些系統(tǒng)上,你可以指令系統(tǒng)你對子進程的退出狀態(tài)沒有興趣,在SysV系統(tǒng)上,可以調(diào)用signal函數(shù),
設(shè)置SIGCLD信號為 SIG_IGN,系統(tǒng)將不產(chǎn)生僵死進程, 詳細說明參見<<高級編程>>10.7節(jié)), 由進程所持有的剩余內(nèi)存被釋放,歸還給系統(tǒng)使用。
2. 怎樣避免僵死進程的出現(xiàn)
需要卻認父進程為每個子進程的終止調(diào)用‘wait()’(或者‘waitpid()’, ‘wait3()’,等等); 或者,在某些系統(tǒng)上,你可以指令系統(tǒng)你對子進程的退出狀態(tài)沒有興趣。(譯者注:在SysV系統(tǒng)上,可以調(diào)用signal函數(shù),設(shè)置SIGCLD信號為 SIG_IGN,系統(tǒng)將不產(chǎn)生僵死進程, 詳細說明參見<<高級編程>>10.7節(jié))。
另一種方法是兩次‘fork()’,而且使緊跟的子進程直接退出,這樣造成孫子進程變成孤兒進程(orphaned),從而init進程將負責(zé)清除它。欲獲得做這個的程序,參看范例章節(jié)的函數(shù)‘fork2()’。
為了忽略子進程狀態(tài),你需要做下面的步驟(查詢你的系統(tǒng)手冊頁以知道這是否正常工作):
struct sigaction sa;
sa.sa_handler = SIG_IGN;
#ifdef SA_NOCLDWAIT
sa.sa_flags = SA_NOCLDWAIT;
#else
sa.sa_flags = 0;
#endif
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);
如果這是成功的,那么‘wait()’函數(shù)集將不再正常工作;如果它們中任何一個被調(diào)用,它們將等待直到*所有*子進程已經(jīng)退出,然后返回失敗,并且 ‘errno==ECHILD’。
另一個技巧是捕獲SIGCHLD信號,然后使信號處理程序調(diào)用‘waitpid()’或 ‘wait3()’。參見范例章節(jié)的完整程序。
參考文獻:
http://www.juntuan.net/hkbc/nixbc/unix/x178.htm
《APUE》
《LKD》
文章出處:http://www.diybl.com/course/6_system/linux/Linuxjs/200888/135107.html