1棚赔、前言
之前在看《unix環(huán)境高級編程》第八章進程時候,提到孤兒進程和僵尸進程,一直對這兩個概念比較模糊玖姑。今天被人問到什么是孤兒進程和僵尸進程,會帶來什么問題慨菱,怎么解決焰络,我只停留在概念上面,沒有深入符喝,倍感慚愧闪彼。晚上回來google了一下,再次參考APUE协饲,認(rèn)真總結(jié)一下畏腕,加深理解。
2茉稠、基本概念
我們知道在unix/linux中描馅,正常情況下,子進程是通過父進程創(chuàng)建的而线,子進程在創(chuàng)建新的進程流昏。子進程的結(jié)束和父進程的運行是一個異步過程,即父進程永遠(yuǎn)無法預(yù)測子進程 到底什么時候結(jié)束。當(dāng)一個 進程完成它的工作終止之后吞获,它的父進程需要調(diào)用wait()或者waitpid()系統(tǒng)調(diào)用取得子進程的終止?fàn)顟B(tài)况凉。
孤兒進程:一個父進程退出,而它的一個或多個子進程還在運行各拷,那么那些子進程將成為孤兒進程刁绒。孤兒進程將被init進程(進程號為1)所收養(yǎng),并由init進程對它們完成狀態(tài)收集工作烤黍。
僵尸進程:一個進程使用fork創(chuàng)建子進程知市,如果子進程退出,而父進程并沒有調(diào)用wait或waitpid獲取子進程的狀態(tài)信息速蕊,那么子進程的進程描述符仍然保存在系統(tǒng)中嫂丙。這種進程稱之為僵尸進程。
3规哲、問題及危害
unix提供了一種機制可以保證只要父進程想知道子進程結(jié)束時的狀態(tài)信息跟啤, 就可以得到。這種機制就是: 在每個進程退出的時候,內(nèi)核釋放該進程所有的資源,包括打開的文件,占用的內(nèi)存等。 但是仍然為其保留一定的信息(包括進程號the process ID,退出狀態(tài)the termination status of the process,運行時間the amount of CPU time taken by the process等)隅肥。直到父進程通過wait / waitpid來取時才釋放竿奏。 但這樣就導(dǎo)致了問題,如果進程不調(diào)用wait / waitpid的話腥放,?那么保留的那段信息就不會釋放泛啸,其進程號就會一直被占用,但是系統(tǒng)所能使用的進程號是有限的秃症,如果大量的產(chǎn)生僵尸進程候址,將因為沒有可用的進程號而導(dǎo)致系統(tǒng)不能產(chǎn)生新的進程. 此即為僵尸進程的危害,應(yīng)當(dāng)避免种柑。
孤兒進程是沒有父進程的進程岗仑,孤兒進程這個重任就落到了init進程身上,init進程就好像是一個民政局莹规,專門負(fù)責(zé)處理孤兒進程的善后工作赔蒲。每當(dāng)出現(xiàn)一個孤兒進程的時候泌神,內(nèi)核就把孤 兒進程的父進程設(shè)置為init良漱,而init進程會循環(huán)地wait()它的已經(jīng)退出的子進程。這樣欢际,當(dāng)一個孤兒進程凄涼地結(jié)束了其生命周期的時候母市,init進程就會代表黨和政府出面處理它的一切善后工作。因此孤兒進程并不會有什么危害损趋。
任何一個子進程(init除外)在exit()之后患久,并非馬上就消失掉,而是留下一個稱為僵尸進程(Zombie)的數(shù)據(jù)結(jié)構(gòu)浑槽,等待父進程處理蒋失。這是每個 子進程在結(jié)束時都要經(jīng)過的階段。如果子進程在exit()之后桐玻,父進程沒有來得及處理篙挽,這時用ps命令就能看到子進程的狀態(tài)是“Z”。如果父進程能及時 處理镊靴,可能用ps命令就來不及看到子進程的僵尸狀態(tài)铣卡,但這并不等于子進程不經(jīng)過僵尸狀態(tài)。 ?如果父進程在子進程結(jié)束之前退出偏竟,則子進程將由init接管煮落。init將會以父進程的身份對僵尸狀態(tài)的子進程進行處理。
僵尸進程危害場景:
例如有個進程踊谋,它定期的產(chǎn) 生一個子進程蝉仇,這個子進程需要做的事情很少,做完它該做的事情之后就退出了,因此這個子進程的生命周期很短量淌,但是骗村,父進程只管生成新的子進程,至于子進程 退出之后的事情呀枢,則一概不聞不問胚股,這樣,系統(tǒng)運行上一段時間之后裙秋,系統(tǒng)中就會存在很多的僵尸進程琅拌,倘若用ps命令查看的話,就會看到很多狀態(tài)為Z的進程摘刑。 嚴(yán)格地來說进宝,僵尸進程并不是問題的根源,罪魁禍?zhǔn)资钱a(chǎn)生出大量僵尸進程的那個父進程枷恕。因此党晋,當(dāng)我們尋求如何消滅系統(tǒng)中大量的僵尸進程時,答案就是把產(chǎn)生大 量僵尸進程的那個元兇槍斃掉(也就是通過kill發(fā)送SIGTERM或者SIGKILL信號啦)徐块。槍斃了元兇進程之后未玻,它產(chǎn)生的僵尸進程就變成了孤兒進 程,這些孤兒進程會被init進程接管胡控,init進程會wait()這些孤兒進程扳剿,釋放它們占用的系統(tǒng)進程表中的資源,這樣昼激,這些已經(jīng)僵死的孤兒進程 就能瞑目而去了庇绽。
注:此為轉(zhuǎn)載他人的勞動成果。