Linux模擬實現(xiàn)僵尸進程
發(fā)布時間:2021-04-26 14:59:14
Linux模擬實現(xiàn)僵尸進程
Z(zombie)-僵尸進程
僵死狀態(tài)(Zombies) 是一個比較特殊的狀態(tài)。當(dāng)進程退出并且父進程沒有讀取到子進程退出的返回代碼是就會產(chǎn)生僵尸進程。
僵尸進程會以終止?fàn)顟B(tài)保存在進程表中,并且會一直等待父進程讀取退出狀態(tài)代碼。
所以,只要子進程退出,父進程還在執(zhí)行,但父進程沒有讀取子進程狀態(tài),子進程進入Z狀態(tài)
模擬實現(xiàn)僵尸進程
//模擬實現(xiàn)僵尸進程
int main()
{
pid_t pid;
pid = fork();
if(pid == -1)
{
perror("創(chuàng)建失敗");
}
if(pid == 0)//孩子進程
{
sleep(3);
printf("孩子進程死亡\n");
}
else if(pid >0)//父進程
{
int times = 10;
while(times--)
{
printf("父進程:%d\n",times);
sleep(1);
}
printf("父進程死亡\n");
}
return 0;
}
測試結(jié)果
整個程序的調(diào)用過程如上,分別在1,2,3處調(diào)用了查看進程命令,1處表示程序正常執(zhí)行,2處表示孩子進程已死亡,變成孤兒進程,3處表示父進程死亡并退出。
這是第一次查看進程的結(jié)果,紅色的方框表示本進程的PID,第一個黃色的方框表示父進程的PID,第二個黃色的框表示進程名,由圖可知,第二個進程的PID為3340,他的父進程為3339,恰好是第一個進程的PID,由此可知第二個進程是第一個進程的子進程,這時父子進程同時在運行。
此時表示孩子進程已死亡,但是父進程還在運行,子進程成為僵尸進程
最后父進程退出,系統(tǒng)回收資源,并將子進程的資源同時回收,進程消失。
僵尸進程的產(chǎn)生
一個進程調(diào)用exit命令結(jié)束自己生命的時候,其實它并沒有真正的被銷毀,而是留下一個稱為“僵尸進程”的數(shù)據(jù)結(jié)構(gòu)。這時它已經(jīng)放棄了幾乎所有內(nèi)存空間,沒有任何可執(zhí)行代碼,也不能被調(diào)度,僅僅在進程列表中保留一個位置(它的內(nèi)核棧還駐留在內(nèi)存中),記載該進程的退出狀態(tài)等有用的信息供其它進程收集。進程的狀態(tài)變成EXIT_ZOMBIE,并且向父進程發(fā)送SIGCHLD信號,Linux默認是忽略該信號的,父進程可以顯示安裝該信號,在信號處理函數(shù)中調(diào)用wait或waitpid函數(shù)等待子進程結(jié)束并將其徹底清除。如果父進程沒有這么做的話,子進程就淪為僵尸進程了。但是在父進程死掉后,它的所有進程都會過繼給init進程,init進程會周期性的去調(diào)用wait系統(tǒng)調(diào)用來清除它的僵尸孩子。
僵尸進程的危害
少數(shù)的僵尸進程并不會對系統(tǒng)的性能有什么影響,但是由于Linux系統(tǒng)對運行的進程數(shù)量是有限制的,所以如果產(chǎn)生的僵尸進程過多,占用了可用的進程號,這將會導(dǎo)致新的進程無法生成。
怎么避免僵尸進程
(1)創(chuàng)建進程的時候調(diào)用兩次fork,而且使緊跟的子進程直接退出,這樣孫子進程成為孤兒進程,init進程將負責(zé)清除這個孤兒進程。
(2)在Linux下可以簡單地將SIGCHLD信號的操作設(shè)為SIG_IGN,這樣內(nèi)核在子進程結(jié)束時不會產(chǎn)生僵尸進程。在SVR4中,如果調(diào)用signal或sigset將SIGCHLD的配置設(shè)置為忽略,也不會產(chǎn)生僵尸進程。
(3)調(diào)用wait或waitpid等待子進程結(jié)束,收集僵尸進程留下的信息,同時使僵尸進程徹底消失。
(注:不能使用kill 后接SIGKILL信號這樣的命令像殺死普通進程一樣殺死僵尸進程,因為僵尸進程是已經(jīng)死掉的進程,它不能再接收任何信號。)
想要了解更多軟件相關(guān)知識、提升自我,就來盛圖科技吧!
- 上一篇:軟件測試的基本問題
- 下一篇:OpenCV是什么?