2010-05-19 9 views
7

如果我fork一个子进程,并且子进程在父呼叫waitpid之前退出,那么由waitpid设置的退出状态信息仍然有效吗?如果是这样,它何时变得无效;即如何确保我可以在子pid上调用waitpid并在任意时间后继续获取有效的退出状态信息,以及如何“清理”(告诉操作系统我不再对退出完成的子进程的状态信息)?对于已经退出的子进程,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; 
} 

回答

10

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

在第一次致电waitpid后,表格中的进程应该消失。我怀疑在您的示例中,您似乎能够拨打waitpid两次的原因很简单,因为如果pid不再存在,waitpid将不会修改status参数。因此,第一个电话应该是工作和填写status,第二个电话应该返回一个错误代码,而不是更改status。您可以通过检查waitpid调用的返回值和/或使用两个不同的status变量来验证此情况。

+0

确实,第二个'waitpid'调用确实失败。我没有想到这个!感谢您指出这一点。 – 2010-05-19 13:22:18

3

操作系统保持终止进程在zombie state直到其父(这可能是init如果原来的父进程提前终止)收集与wait(2)系统调用的退出状态。所以答案是 - 进程的退出状态不会变为无效

2

是的。

man page

终止,但一直没有 被等待变成“僵尸”一个孩子。 内核为了让 父以后进行等待,以 获得关于孩子的信息保持最小的一组关于僵尸进程 (PID,终止状态,资源 使用信息) 信息。

相关问题