现在的位置: 首页 > 综合 > 正文

僵尸進程和領養進程總結

2013年04月21日 ⁄ 综合 ⁄ 共 1416字 ⁄ 字号 评论关闭

關於僵尸進程,網上眾說紛紜,越看越迷糊!今天好好的整理一下!!!!

進程fork出子進程,這是一切的前提!而且僵尸進程和領養進程都是針對子進程來講的,這一點要搞清楚。

正常流程:

第一:父進程終止時,內核逐級檢查所有活動的進程,以判斷它是否是正要終止進程的子進程,如果是,則將該進程的父進程改為init進程,保證了每個進程都是自己的父進程。

注意,此時內核檢查的是“活動”的進程。這些進程被稱之為“領養的進程”。

第二:如果,父進程終止時,子進程早已經結束。此時,父進程的正確處理方式是調用wait/waitpid來監控子進程。子進程結束之後,父進程會清除子進程的一些進程信息。這樣也是無可厚非,很正常的。但是要注意,這是時候僵尸進程就要出現了。什麽時候出現?就是在“子進程已經終止,而父進程尚未終止”這個時刻。而當父進程終止的時候,就會返回到上面第一條的流程。

第三:第一條中所說的“被領養的進程”,會不會再次成為僵尸進程?答案是不會的。因為他們的父進程是init,當這些進程終止的時候,init會wait/waitpid,因此會清除這些進程的信息。

所以,只有一種情況會出現僵尸進程,即:子進程先退出,並且父進程沒有wait/waitpid這個子進程,此時這個子進程就變成了僵尸進程。試想,如果一個進程一直運行,并fork了很多子進程,而本身既不會退出,而且不會wait子進程,那麼就會產生大量的僵尸進程!針對這種情況,舉個例子看一看。

#include <unistd.h>   
#include <stdlib.h>   
#include <stdio.h>   
#include <sys/wait.h>   
  
const char cmd_init[]="ps -o pid,ppid,state,tty,command";  
  
int main(int argc,char **argv)  
{  
        pid_t   pid;
        int n = 5;
        /*子進程不斷的fork子進程*/
        for(n;n>0;n--){
        	pid = fork();
        	if(pid == 0)
        		exit(0);
        }

        sleep(5);
        system(cmd_init);
        exit(0);  
}

編譯運行,輸出結果,如下:

21096 20254 S pts/2    ./my_zombie3
21097 21096 Z pts/2    [my_zombie3] <defunct>
21098 21096 Z pts/2    [my_zombie3] <defunct>
21099 21096 Z pts/2    [my_zombie3] <defunct>
21100 21096 Z pts/2    [my_zombie3] <defunct>
21101 21096 Z pts/2    [my_zombie3] <defunct>
21104 21096 R pts/2    ps -o pid,ppid,state,tty,command

等待該程序運行退出之後,再次查看進程情況,使用 ps -ax。發現僵尸進程已經沒有了,這是因為我們上面第一條的流程。

疑問,這些曾經的僵尸進程,是被init領養了呢,還是在父進程退出的時候給清除了?

可以肯定是被init領養了,爲什麽呢?因為他們的父進程并沒有使用wait/waitpid函數來清除進程信息。

也就是說,這些子進程由短暫的“僵尸進程”變成了“被領養進程”。

ps:當談論到init的子進程的時候,我們是無法判斷這個子進程是被init調用fork()產生的,還是由別的進程領養過來的!

抱歉!评论已关闭.