僵尸进程的父进程终止后会发生什么?

6

我很好奇,如果一个进程的父进程不关心它,那么这个僵尸进程会发生什么。

假设我们有一个父进程和一个子进程。子进程在父进程之前终止。

根据APUE:

内核为每个终止的进程保留少量信息...最小限度包括进程ID、进程的终止状态...

父进程需要使用waitpid()获取此信息。
但是,如果父进程在没有等待子进程的情况下退出,会发生什么:

内核是否删除此信息(显然没有用)?
还是一直收集这些垃圾?
这是特定于实现的吗?
还是有一种标准方法来处理这种情况?


init进程成为子进程的父进程,init从进程表中清除条目。 - Grijesh Chauhan
1个回答

10

孤儿进程会自动被init接管,它有一个标准的SIGCHLD处理程序,只会丢弃已死进程的任何退出状态。

在你的情况下,如果僵尸进程的父进程死亡,则将由init接管并清理该僵尸进程。

以下代码测试了这一点:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>


int main() {
    pid_t child_pid;
    if (child_pid = fork()) { // fork a child, child will exit straight away
        char name[128];
        sprintf(name, "/proc/%d/stat", child_pid);
        char line[2048];

        // read childs /proc/pid/stat, field 3 will give its status
        FILE * fp = fopen(name, "r");

        while (fgets(line, sizeof(line), fp))
            puts(line);

        fclose(fp);

        usleep(5000000);

        // by now the child will have exited for sure, repeat
        fp = fopen(name, "r");

        while (fgets(line, sizeof(line), fp))
            puts(line);

        fclose(fp);

        // make another child to repeat the process and exit the parent
        if (!fork()) {
            usleep(5000000);
            // both parent and child will have exited by now

            fp = fopen(name, "r");

            // this should fail because init has already cleaned up the child
            if (!fp) {
                perror("fopen");
                return -1;
            }

            while (fgets(line, sizeof(line), fp))
                puts(line);

            fclose(fp);
        }

    }

    return 0;
}

由于子进程已经终止,SIGCHLD信号是否仍会生成?我认为当子进程终止时会生成该信号(如果我错了请纠正我)。 - mohit
@mohit,好问题,可能不行。我无法确定是否有一种方法可以在用户进程中采用一个进程。无论如何,init会清理子进程并丢弃其退出状态。整个被init收养是为了确保孤儿僵尸不会停留在系统中。 - Sergey L.
+1,对于这个程序来说真的很好解释了发生了什么。然而,我对它是如何实现的很感兴趣。如果这是特定于实现的,还是有标准的方法? - mohit
1
@mohit 这是Unix和类Unix的标准。关于SIGCHLD - init定期等待所有子进程清理它们(如果需要)。来自:http://en.wikipedia.org/wiki/Zombie_process - Sergey L.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接