7

如果我fork是子进程,并且子进程在父调用之前退出waitpid,那么设置的退出状态信息是否waitpid仍然有效?如果是,什么时候变得无效;即,如何确保我可以调用waitpid子 pid 并在任意时间后继续获取有效的退出状态信息,以及如何“清理”(告诉操作系统我不再对退出感兴趣已完成子进程的状态信息)?

我在玩下面的代码,似乎退出状态信息在孩子完成后至少几秒钟内有效,但我不知道多久或如何通知操作系统我不会再次调用waitpid

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
    pid_t pid = fork();

    if (pid < 0) {
        fprintf(stderr, "Failed to fork\n");
        return EXIT_FAILURE;
    }
    else if (pid == 0) { // code for child process
        _exit(17);
    }
    else { // code for parent
        sleep(3);

        int status;
        waitpid(pid, &status, 0);
        waitpid(pid, &status, 0); // call `waitpid` again just to see if the first call had an effect
        assert(WIFEXITED(status));
        assert(WEXITSTATUS(status) == 17);
    }

    return EXIT_SUCCESS;
}
4

3 回答 3

13

是的,waitpid将在孩子退出后工作。操作系统将在进程表中保留子进程的条目(包括退出状态),直到父调用waitpid(或另一个wait-family 函数)或直到父退出(此时init进程收集状态)。这就是一个“僵尸”进程:一个已经退出的进程仍然驻留在进程表中,正是为了这个目的。

表中的进程条目应在第一次调用 后消失waitpid。我怀疑在您的示例中您似乎可以调用waitpid两次的原因仅仅是因为如果不再存在waitpid则不会修改status参数。pid所以第一次调用应该工作并填写status,第二次调用应该返回一个错误代码而不是改变status。您可以通过检查waitpid调用的返回值和/或使用两个不同的status变量来验证这一点。

于 2010-05-19T13:02:25.730 回答
3

操作系统将终止的进程保持在僵尸状态init,直到其父进程(如果原始父进程更早终止,则可能是该进程)通过wait(2)系统调用收集该退出状态。所以答案是——进程的退出状态不会变为无效

于 2010-05-19T13:02:52.040 回答
2

是的。

手册页

终止但没有等待的孩子成为“僵尸”。内核维护有关僵尸进程的最小信息集(PID、终止状态、资源使用信息),以便允许父进程稍后执行等待以获取有关子进程的信息。

于 2010-05-19T13:06:27.643 回答