Posted on 2008-08-21 18:24
Prayer 閱讀(488)
評論(0) 編輯 收藏 引用 所屬分類:
LINUX/UNIX/AIX
僵尸進程
--是指一個已經(jīng)終止、但是其父進程尚未對其進行善后處理(獲取終止進程的有關(guān)信息,釋放它仍占用的資源)的進程被稱為"僵尸進程"(zombie)。
怎樣產(chǎn)生僵尸進程的:
一個進程在調(diào)用exit命令結(jié)束自己的生命的時候,其實它并沒有真正的被銷毀,而是留下一個稱為僵尸進程(Zombie)的數(shù)據(jù)結(jié)構(gòu)(系統(tǒng)調(diào)用exit, 它的作用是使進程退出,但也僅僅限于將一個正常的進程變成一個僵尸進程,并不能將其完全銷毀)。
在Linux進程的狀態(tài)中,僵尸進程是非常特殊的一種,它已經(jīng)放棄了幾乎所有內(nèi)存空間,沒有任何可執(zhí)行代碼,也不能被調(diào)度,僅僅在進程列表中保留一個位置,記載該進程的退出狀態(tài)等信息供其他進程收集,除此之外,僵尸進程不再占有任何內(nèi)存空間。它需要它的父進程來為它收尸,如果他的父進程沒安裝SIGCHLD信號處理函數(shù)調(diào)用wait或waitpid()等待子進程結(jié)束,又沒有顯式忽略該信號,那么它就一直保持僵尸狀態(tài),如果這時父進程結(jié)束了,那么init進程自動會接手這個子進程,為它收尸,它還是能被清除的。但是如果如果父進程是一個循環(huán),不會結(jié)束,那么子進程就會一直保持僵尸狀態(tài),這就是為什么系統(tǒng)中有時會有很多的僵尸進程。
怎么查看僵尸進程:
利用命令ps,可以看到有父進程ID為1的進程是孤兒進程;s(state)狀態(tài)為Z的是僵尸進程。
注意:孤兒進程(orphan process)是尚未終止但已停止(相當(dāng)于前臺掛起)的進程,但其父進程已經(jīng)終止,由init收養(yǎng);而僵尸進程則是已終止的進程,其父進程不一定終止。
怎樣來清除僵尸進程:
1.改寫父進程,在子進程死后要為它收尸。具體做法是接管SIGCHLD信號。子進程死后,會發(fā)送SIGCHLD信號給父進程,父進程收到此信號后,執(zhí)行 waitpid()函數(shù)為子進程收尸。這是基于這樣的原理:就算父進程沒有調(diào)用wait,內(nèi)核也會向它發(fā)送SIGCHLD消息,盡管對的默認處理是忽略, 如果想響應(yīng)這個消息,可以設(shè)置一個處理函數(shù)。
2.把父進程殺掉。父進程死后,僵尸進程成為"孤兒進程",過繼給1號進程init,init始終會負責(zé)清理僵尸進程,關(guān)機或重啟后所有僵尸進程都會消失。
避免Zombie Process的方法:
1)在SVR4中,如果調(diào)用signal或sigset將SIGCHLD的配置設(shè)置為忽略,則不會產(chǎn)生僵死子進程。另外,使用SVR4版的sigaction,則可設(shè)置SA_NOCLDWAIT標志以避免子進程僵死。 Linux中也可使用這個,在一個程序的開始調(diào)用這個函數(shù)signal(SIGCHLD,SIG_IGN)。
2)調(diào)用fork兩次。
3)用waitpid等待子進程返回。