在《Unix环境中的高级编程》一书中,wait and waitpid一节说:
waitpid函数不等待首先终止的子函数;它有许多选项来控制它等待的进程。
我读到这篇文章时,就好像子进程先退出,而父进程还没有调用waitpid
函数一样,子进程不会被等待,退出后将作为僵尸进程。
所以我写了一些代码来测试:
int main() {
pid_t pid = fork();
if (pid == 0) {
// child process
printf("Child Process ID: %d n", getpid());
printf("Child Process Quitn");
exit(0);
} else {
// parent
sleep(5);
printf("Parent Process ID: %d n", getpid());
printf("Wait child %d ...n", pid);
int status;
waitpid(pid, &status, 0);
printf("waitpid calledn");
sleep(5);
}
return 0;
}
程序首先打印出"子进程ID"one_answers"子进程退出",当父进程仍在休眠时,在另一个终端窗口中,如果我使用ps -el | grep 'Z'
,我可以看到这个子进程是<defunct>
(僵尸(。
5秒后,只要名为waitpid
的父进程在另一个终端窗口中,使用ps -el | grep 'Z'
就不会再显示僵尸子进程,所以这意味着子进程已经被等待,不再是僵尸。
看来父进程总是可以等待具有waitpid
的子进程,那么我该如何解释这个"waitpid函数不等待首先终止的子进程"呢?
如果您完成了报价(正如现在在问题中完成的那样(,您会发现waitpid()
(比wait()
(更灵活。
POSIX规范中写道:
pid参数指定一组请求状态的子进程。
waitpid()
功能应仅返回该集合中的子进程的状态:
如果pid等于
(pid_t)-1
,则会请求任何子进程的状态。在这方面,waitpid()
则等效于wait()
。如果pid大于0,则指定请求状态的单个子进程的进程ID。
如果pid为0,则会为进程组ID等于调用进程ID的任何子进程请求状态。
如果pid小于
(pid_t)-1
,则会为进程组ID等于pid绝对值的任何子进程请求状态。
因此,正如名言所说,waitpid()
并不总是(只(等待第一个孩子死去;您可以更精确地选择您感兴趣的一个或多个子级。此外,您还可以选择WNOHANG
等选项,这意味着如果没有符合标准的已死亡子级(但至少有一个进程符合标准(,则函数将返回。如果没有符合标准的孩子,你会得到不同的状态。