对c编程中的“僵尸进程”感到困惑

时间:2016-04-27 01:39:36

标签: c fork zombie-process

  

问题 :如何确定哪一个产生“ zombie 进程

// Case 1

while(fork())

    ; 

exit(0);


// Case 2

while(!fork())

     ;

exit(0);

我知道“僵尸”是 - 当一个进程终止并仍然消耗资源时。 (或者至少我认为就是这样)

我认为案例1 生成僵尸进程的情况,因为它会在错误时返回-1,而while(-1)= true所以它会继续分叉吗?我不太确定。任何见解都会很棒,

BTW:此代码在 c 编程语言的 Linux 环境中运行

提前致谢

1 个答案:

答案 0 :(得分:3)

僵尸进程是一个终止子进程,但父进程尚未等待。子进程通常由fork创建:

int pid = fork();
if (pid < 0) {
     // fork failed
} else if (pid == 0) {
    // this is the child process
}
// this is the parent

fork向子进程返回0,向父进程返回正pid。终止时有两种情况:

  1. 在父母之前退出子女,然后孩子成为一个&#34;僵尸&#34;进程,直到父母调用等待系列函数来获得孩子的退出状态。

  2. 在子进程之前退出父进程,然后将子进程重新设置为init进程的子进程,init进程将在子进程中调用wait等待。这是有效的,因为父节点在其子节点退出时将收到SIGCHLD信号,并且它可以在信号处理程序中调用wait。所以在这种情况下,不会创建僵尸。

  3. 另外,请注意,如果父母忽略SIGCHLD,posix定义不会创建僵尸:

      

    POSIX.1-2001指定如果将SIGCHLD的处置设置为SIG_IGN或为SIGCHLD设置SA_NOCLDWAIT标志(请参阅sigaction(2)),则终止的子节点不会          变成僵尸,并且调用wait()或waitpid()将阻塞,直到所有子节点都终止,然后失败并将errno设置为ECHILD。 (最初的POSIX标准离开了          将SIGCHLD设置为未指定的SIG_IGN的行为。请注意,即使SIGCHLD的默认处置是&#34;忽略&#34;,明确地将处置设置为SIG_IGN结果          在僵尸加工儿童的不同治疗中。)

    对于OP中的两个案例:

    // Case 1
    while(fork())  // same as while(fork() != 0)
        ;
    
    exit(0);
    
    
    // Case 2
    while(!fork()) // same as while(fork() == 0)
        ;
    
    exit(0);
    

    第一个代码在父级中保持分叉,无论它是否成功,结果子级将立即退出,因为返回值将为0.因为父级挂起在while循环中,无论fork成功还是失败(fork只为孩子返回0),所有孩子都会变成僵尸。

    对于第二种情况,当fork返回时父节点立即退出,但是子节点将继续分叉,并且这个子节点将再次执行相同的操作,即它将立即退出,并且它创建的子节点将继续分叉。在这种情况下,由于父出口,它的所有子进程都将重新定义到init进程,因此不会创建僵尸。