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

发布于 2024-09-02 06:23:41 字数 1038 浏览 9 评论 0原文

如果我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;
}

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? If so, when does it become not valid; i.e., 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)?

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:

#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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

忆梦 2024-09-09 06:23:41

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

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

Yes, waitpid will work after the child has exited. 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). 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. 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. 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. You can verify this by inspecting the return values of the waitpid calls and/or using two different status variables.

土豪我们做朋友吧 2024-09-09 06:23:41

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

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. So the answer is - the exit status of the process does not become invalid.

恋竹姑娘 2024-09-09 06:23:41

是的。

手册页

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文