如果我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;
}
答案 0 :(得分:11)
是的,waitpid
将在孩子退出后生效。操作系统将保留子进程在进程表中的条目(包括退出状态),直到父进程调用waitpid
(或另一个wait
- 系列函数)或直到父进程退出(此时为状态由init
进程收集。这就是“僵尸”进程的原因:为了这个目的,已经退出的进程仍然驻留在进程表中。
第一次调用waitpid
后,表格中的流程输入应该消失。我怀疑在您的示例中您似乎能够两次调用waitpid
的原因仅仅是因为如果waitpid
不再存在,status
将不会修改pid
参数。因此,第一个调用应该正常工作并填写status
,第二个调用应返回错误代码而不是更改status
。您可以通过检查waitpid
调用的返回值和/或使用两个不同的status
变量来验证这一点。
答案 1 :(得分:3)
操作系统在zombie state中保留已终止的进程,直到其父进程(如果原始父进程先前终止,可能是init
)收集具有wait(2)
系统调用的退出状态。所以答案是 - 进程的退出状态不会变为无效。
答案 2 :(得分:2)