简体   繁体   English

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

[英]Does waitpid yield valid status information for a child process that has already exited?

If I fork a child process, and the child process exits before the parent calls waitpid , then is the exit status information that is set by waitpid still valid? 如果我fork子进程,并且子进程在父调用waitpid之前退出,那么waitpid设置的退出状态信息是否仍然有效? If so, when does it become not valid; 如果是的话,什么时候变得无效; ie, how do I ensure that I can call waitpid on the child pid and continue to get valid exit status information after an arbitrary amount of time, and how do I "clean up" (tell the OS that I am no longer interested in the exit status information for the finished child process)? 即,如何确保我可以在子pid上调用waitpid并在任意时间后继续获取有效的退出状态信息,以及如何“清理”(告诉操作系统我不再对已完成的子进程的退出状态信息)?

I was playing around with the following code, and it appears that the exit status information is valid for at least a few seconds after the child finishes, but I do not know for how long or how to inform the OS that I won't be calling waitpid again: 我正在玩下面的代码,似乎退出状态信息在孩子完成后至少几秒钟有效,但我不知道多长时间或如何通知操作系统我不会再次调用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;
}

Yes, waitpid will work after the child has exited. 是的, waitpid将在孩子退出后工作。 The OS will keep a child process' entry in the process table (including exit status) around until the parent calls waitpid (or another wait -family function) or until the parent exits (at which point the status is collected by the init process). 操作系统将保持子进程在进程表中的条目(包括退出状态),直到父进程调用waitpid (或另一个wait -family函数)或直到父进程退出(此时init进程收集状态) 。 This is what a "zombie" process is: a process that has exited by is still resident in the process table for exactly this purpose. 这就是“僵尸”进程的原因:已经退出的进程仍然驻留在进程表中以实现此目的。

The process' entry in the table should go away after the first call to waitpid . 第一次调用waitpid后,表中的进程'条目应该消失。 I suspect the reason that in your example you seem to be able to call waitpid twice is simply because waitpid will not modify the status argument if pid no longer exists. 我怀疑在你的例子中你似乎能够两次调用waitpid原因仅仅是因为如果pid不再存在, waitpid将不会修改status参数。 So the first call should be working and filling in status , and the second call should be returning an error code and not changing status . 所以第一次调用应该工作并填写status ,第二次调用应该返回错误代码而不是改变status You can verify this by inspecting the return values of the waitpid calls and/or using two different status variables. 您可以通过检查waitpid调用的返回值和/或使用两个不同的status变量来验证这一点。

The OS keeps terminated process in a zombie state until its parent (which might be the init if the original parent process terminated earlier) collects that exit status with wait(2) system call. 操作系统将僵持状态的终止进程保持到其父级(如果原始父进程先前终止可能是init ),则使用wait(2)系统调用收集该退出状态。 So the answer is - the exit status of the process does not become invalid . 所以答案是 - 进程的退出状态不会变得无效

Yes. 是。

From the man page : 手册页

A child that terminates, but has not been waited for becomes a "zombie". 终止但尚未等待的孩子变成了“僵尸”。 The kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a wait to obtain information about the child. 内核维护有关僵尸进程(PID,终止状态,资源使用信息)的最小信息集,以便允许父进程稍后执行等待以获得关于子进程的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM