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

时间:2010-05-19 12:56:46

标签: c fork waitpid posix-api

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

我正在使用以下代码,看起来退出状态信息在孩子完成后至少几秒内有效,但我不知道多长时间或如何通知操作系统我赢了不要再打电话给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;
}

3 个答案:

答案 0 :(得分:11)

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

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

答案 1 :(得分:3)

操作系统在zombie state中保留已终止的进程,直到其父进程(如果原始父进程先前终止,可能是init)收集具有wait(2)系统调用的退出状态。所以答案是 - 进程的退出状态不会变为无效

答案 2 :(得分:2)

来自man page

  

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