僵尸進(jìn)程并不可怕,可怕的是量大。僵尸進(jìn)程是有它存在的意義的。以下解釋摘自百度百科:
由于子進(jìn)程的結(jié)束和父進(jìn)程的運(yùn)行是一個(gè)異步過程,即父進(jìn)程永遠(yuǎn)無(wú)法預(yù)測(cè)子進(jìn)程 到底什么時(shí)候結(jié)束. 那么會(huì)不會(huì)因?yàn)楦高M(jìn)程太忙來(lái)不及wait子進(jìn)程,或者說(shuō)不知道 子進(jìn)程什么時(shí)候結(jié)束,而丟失子進(jìn)程結(jié)束時(shí)的狀態(tài)信息呢? 不會(huì)。因?yàn)閁NⅨ提供了一種機(jī)制可以保證只要父進(jìn)程想知道子進(jìn)程結(jié)束時(shí)的狀態(tài)信息, 就可以得到。這種機(jī)制就是: 在每個(gè)進(jìn)程退出的時(shí)候,內(nèi)核釋
放該進(jìn)程所有的資源,包括打開的文件,占用的內(nèi)存等。但是仍然為其保留一定的信息(包括進(jìn)程號(hào)the process ID,退出狀態(tài)the
termination status of the process,運(yùn)行時(shí)間the amount of CPU time taken by
the process等)。直到父進(jìn)程通過wait / waitpid來(lái)取時(shí)才釋放. 但這樣就導(dǎo)致了問題,如果進(jìn)程不調(diào)用wait / waitpid的話,那么保留的那段信息就不會(huì)釋放,其進(jìn)程號(hào)就會(huì)一直被占用,但是系統(tǒng)所能使用的進(jìn)程號(hào)是有限的,如果大量的產(chǎn)生僵死進(jìn)程,將因?yàn)闆]有可用的進(jìn)程號(hào)而導(dǎo)致系統(tǒng)不能產(chǎn)生新的進(jìn)程. 此即為僵尸進(jìn)程的危害,應(yīng)當(dāng)避免。
僵尸進(jìn)程的避免:
⒈父進(jìn)程通過wait和waitpid等函數(shù)等待子進(jìn)程結(jié)束,這會(huì)導(dǎo)致父進(jìn)程掛起。
⒉ 如果父進(jìn)程很忙,那么可以用signal函數(shù)為SIGCHLD安裝handler,因?yàn)樽舆M(jìn)程結(jié)束后, 父進(jìn)程會(huì)收到該信號(hào),可以在handler中調(diào)用wait回收。
⒊ 如果父進(jìn)程不關(guān)心子進(jìn)程什么時(shí)候結(jié)束,那么可以用signal(SIGCHLD,SIG_IGN) 通知內(nèi)核,自己對(duì)子進(jìn)程的結(jié)束不感興趣,那么子進(jìn)程結(jié)束后,內(nèi)核會(huì)回收, 并不再給父進(jìn)程發(fā)送信號(hào)。
⒋ 還有一些技巧,就是fork兩次,父進(jìn)程fork一個(gè)子進(jìn)程,然后繼續(xù)工作,子進(jìn)程fork一 個(gè)孫進(jìn)程后退出,那么孫進(jìn)程被init接管,孫進(jìn)程結(jié)束后,init會(huì)回收。不過子進(jìn)程的回收 還要自己做。