waitpid 是否会为已退出的子进程生成有效的状态信息?
如果我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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,
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 callswaitpid
(or anotherwait
-family function) or until the parent exits (at which point the status is collected by theinit
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 callwaitpid
twice is simply becausewaitpid
will not modify thestatus
argument ifpid
no longer exists. So the first call should be working and filling instatus
, and the second call should be returning an error code and not changingstatus
. You can verify this by inspecting the return values of thewaitpid
calls and/or using two differentstatus
variables.操作系统将终止的进程保持在僵尸状态,直到其父进程(可能是
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 withwait(2)
system call. So the answer is - the exit status of the process does not become invalid.是的。
从 手册页:
Yes.
From the man page: