什么是僵尸进程与孤儿进程
1、什么是僵尸進(jìn)程和孤兒進(jìn)程:
????????在 Unix/Linux 系統(tǒng)中,正常情況下,子進(jìn)程是通過(guò)父進(jìn)程創(chuàng)建的,且兩者的運(yùn)行是相互獨(dú)立的,父進(jìn)程永遠(yuǎn)無(wú)法預(yù)測(cè)子進(jìn)程到底什么時(shí)候結(jié)束。當(dāng)一個(gè)進(jìn)程調(diào)用 exit 命令結(jié)束自己的生命時(shí),其實(shí)它并沒(méi)有真正的被銷毀,內(nèi)核只是釋放了該進(jìn)程的所有資源,包括打開(kāi)的文件、占用的內(nèi)存等,但是留下一個(gè)稱為僵尸進(jìn)程的數(shù)據(jù)結(jié)構(gòu),這個(gè)結(jié)構(gòu)保留了一定的信息(包括進(jìn)程號(hào) the process ID,退出狀態(tài),運(yùn)行時(shí)間),這些信息直到父進(jìn)程通過(guò) wait()/waitpid() 來(lái)取時(shí)才釋放。這樣設(shè)計(jì)的目的主要是保證只要父進(jìn)程想知道子進(jìn)程結(jié)束時(shí)的狀態(tài)信息,就可以得到
-
僵尸進(jìn)程:一個(gè)進(jìn)程使用 fork 創(chuàng)建子進(jìn)程,如果子進(jìn)程退出,而父進(jìn)程并沒(méi)有調(diào)用 wait 或 waitpid 獲取子進(jìn)程的狀態(tài)信息,那么子進(jìn)程的進(jìn)程描述符仍然保存在系統(tǒng)中,這種進(jìn)程稱之為僵死進(jìn)程。
-
孤兒進(jìn)程:一個(gè)父進(jìn)程退出,而它的一個(gè)或多個(gè)子進(jìn)程還在運(yùn)行,那么這些子進(jìn)程將成為孤兒進(jìn)程。孤兒進(jìn)程將被 init 進(jìn)程(進(jìn)程號(hào)為1)所收養(yǎng),并由 init 進(jìn)程對(duì)它們完成狀態(tài)收集工作。
2、僵尸進(jìn)程與孤兒進(jìn)程的問(wèn)題危害:
????????僵尸進(jìn)程雖然不占有任何內(nèi)存空間,但如果父進(jìn)程不調(diào)用 wait() / waitpid() 的話,那么保留的信息就不會(huì)釋放,其進(jìn)程號(hào)就會(huì)一直被占用,而系統(tǒng)所能使用的進(jìn)程號(hào)是有限的,如果大量的產(chǎn)生僵死進(jìn)程,將因?yàn)闆](méi)有可用的進(jìn)程號(hào)而導(dǎo)致系統(tǒng)不能產(chǎn)生新的進(jìn)程,此即為僵尸進(jìn)程的危害。
????????孤兒進(jìn)程是沒(méi)有父進(jìn)程的進(jìn)程,孤兒進(jìn)程這個(gè)重任就落到了 init 進(jìn)程身上,init 進(jìn)程就好像是一個(gè)民政局,專門(mén)負(fù)責(zé)處理孤兒進(jìn)程的善后工作。每當(dāng)出現(xiàn)一個(gè)孤兒進(jìn)程的時(shí)候,內(nèi)核就把孤兒進(jìn)程的父進(jìn)程設(shè)置為 init,而 init 進(jìn)程會(huì)循環(huán)地 wait() 它的已經(jīng)退出的子進(jìn)程。這樣,當(dāng)一個(gè)孤兒進(jìn)程凄涼地結(jié)束了其生命周期的時(shí)候,init 進(jìn)程就會(huì)出面處理它的一切善后工作。因此孤兒進(jìn)程并不會(huì)有什么危害。
如果子進(jìn)程在 exit() 之后,父進(jìn)程沒(méi)有來(lái)得及處理,這時(shí)用 ps 命令就能看到子進(jìn)程的狀態(tài)是“Z”。如果父進(jìn)程能及時(shí)處理,可能用 ps 命令就來(lái)不及看到子進(jìn)程的僵尸狀態(tài),但這并不等于子進(jìn)程不經(jīng)過(guò)僵尸狀態(tài)。 如果父進(jìn)程在子進(jìn)程結(jié)束之前退出,則子進(jìn)程將由 init 接管。init 將會(huì)以父進(jìn)程的身份對(duì)僵尸狀態(tài)的子進(jìn)程進(jìn)行處理。
3、如果解決僵尸進(jìn)程造成的問(wèn)題:
(1)方案一:父進(jìn)程通過(guò) wait 和 waitpid 等函數(shù)等待子進(jìn)程結(jié)束,但這會(huì)導(dǎo)致父進(jìn)程掛起,所以這并不是一個(gè)好辦法,父進(jìn)程如果不能和子進(jìn)程并發(fā)執(zhí)行的話,那我們創(chuàng)建子進(jìn)程的意義就沒(méi)有。同時(shí)一個(gè) wait 只能解決一個(gè)子進(jìn)程,如果有多個(gè)子進(jìn)程就要用到多個(gè) wait
(2)方案二:通過(guò)信號(hào)機(jī)制:
????????子進(jìn)程退出時(shí),向父進(jìn)程發(fā)送 SIGCHILD 信號(hào),父進(jìn)程處理 SIGCHILD 信號(hào),在信號(hào)處理函數(shù)中調(diào)用 wait 進(jìn)行處理僵尸進(jìn)程。
(3)方案三:fork兩次:
????????原理是將進(jìn)程成為孤兒進(jìn)程,從而其的父進(jìn)程變?yōu)?init 進(jìn)程,通過(guò) init 進(jìn)程處理僵尸進(jìn)程。具體操作為:父進(jìn)程一次 fork() 后產(chǎn)生一個(gè)子進(jìn)程隨后立即執(zhí)行 wait(NULL) 來(lái)等待子進(jìn)程結(jié)束,然后子進(jìn)程 fork() 后產(chǎn)生孫子進(jìn)程隨后立即exit(0)。這樣子進(jìn)程順利終止(父進(jìn)程僅僅給子進(jìn)程收尸,并不需要子進(jìn)程的返回值),然后父進(jìn)程繼續(xù)執(zhí)行。這時(shí)的孫子進(jìn)程由于失去了它的父進(jìn)程(即是父進(jìn)程的子進(jìn)程),將被轉(zhuǎn)交給Init進(jìn)程托管。于是父進(jìn)程與孫子進(jìn)程無(wú)繼承關(guān)系了,它們的父進(jìn)程均為Init,Init進(jìn)程在其子進(jìn)程結(jié)束時(shí)會(huì)自動(dòng)收尸,這樣也就不會(huì)產(chǎn)生僵死進(jìn)程了
(4)方案四:kill 父進(jìn)程:
????????嚴(yán)格地來(lái)說(shuō),僵死進(jìn)程并不是問(wèn)題的根源,罪魁禍?zhǔn)资钱a(chǎn)生出大量僵死進(jìn)程的那個(gè)父進(jìn)程。因此,當(dāng)我們尋求如何消滅系統(tǒng)中大量的僵死進(jìn)程時(shí),答案就是把產(chǎn)生大量僵死進(jìn)程的那個(gè)元兇槍斃掉(也就是通過(guò) kill 發(fā)送 SIGTERM 或者 SIGKILL 信號(hào)啦)。槍斃了元兇進(jìn)程之后,它產(chǎn)生的僵死進(jìn)程就變成了孤兒進(jìn) 程,這些孤兒進(jìn)程會(huì)被 init 進(jìn)程接管,init 進(jìn)程會(huì) wait() 這些孤兒進(jìn)程,釋放它們占用的系統(tǒng)進(jìn)程表中的資源,這樣,這些已經(jīng)僵死的孤兒進(jìn)程就能瞑目而去了。
參考文章:
https://www.cnblogs.com/Anker/p/3271773.html
https://www.cnblogs.com/jian-99/p/7739369.html
總結(jié)
以上是生活随笔為你收集整理的什么是僵尸进程与孤儿进程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: JUC多线程:Atomic原子类与CAS
- 下一篇: Tomcat 的类加载机制