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


- 上一篇:軟件測試的基本問題
- 下一篇:OpenCV是什么?