waitpid是否为已经退出的子进程生成有效状态信息?

Dan*_*ien 7 c fork waitpid posix-api

如果我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;
}
Run Code Online (Sandbox Code Playgroud)

Tyl*_*nry 12

是的,waitpid孩子退出后会工作.操作系统将保持子进程在进程表中的条目(包括退出状态),直到父进程调用waitpid(或其他wait-family函数)或直到父init进程退出(此时进程收集状态).这就是"僵尸"进程的原因:已经退出的进程仍然驻留在进程表中以实现此目的.

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