基于此:http://man7.org/tlpi/code/online/book/procexec/multi_wait.c.html
int
main(int argc, char *argv[])
{
int numDead; /* Number of children so far waited for */
pid_t childPid; /* PID of waited for child */
int j;
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s sleep-time...\n", argv[0]);
setbuf(stdout, NULL); /* Disable buffering of stdout */
for (j = 1; j < argc; j++) { /* Create one child for each argument */
switch (fork()) {
case -1:
errExit("fork");
case 0: /* Child sleeps for a while then exits */
printf("[%s] child %d started with PID %ld, sleeping %s "
"seconds\n", currTime("%T"), j, (long) getpid(),
argv[j]);
sleep(getInt(argv[j], GN_NONNEG, "sleep-time"));
_exit(EXIT_SUCCESS);
default: /* Parent just continues around loop */
break;
}
}
numDead = 0;
for (;;) { /* Parent waits for each child to exit */
childPid = wait(NULL);
if (childPid == -1) {
if (errno == ECHILD) {
printf("No more children - bye!\n");
exit(EXIT_SUCCESS);
} else { /* Some other (unexpected) error */
errExit("wait");
}
}
numDead++;
printf("[%s] wait() returned child PID %ld (numDead=%d)\n",
currTime("%T"), (long) childPid, numDead);
}
}
出错时,wait返回-1。一个可能的错误是调用 过程没有(以前未被等待的)孩子,由表示 错误值 ECHILD 。
$ ./multi_wait 7 1 4
[13:41:00] child 1 started with PID 21835, sleeping 7 seconds
[13:41:00] child 2 started with PID 21836, sleeping 1 seconds
[13:41:00] child 3 started with PID 21837, sleeping 4 seconds
[13:41:01] wait() returned child PID 21836 (numDead=1)
[13:41:04] wait() returned child PID 21837 (numDead=2)
[13:41:07] wait() returned child PID 21835 (numDead=3)
No more children - bye!
问题
系统如何知道没有更多的孩子无法接受并返回ECHILD。 例如,在这个例子中,如果有些孩子睡了很长时间怎么办?
答案 0 :(得分:2)
系统会跟踪每个流程。您可以使用命令ps xf
查看Ubuntu系统上的进程树。
特别是,在此列表中,您可以看到每个进程的状态:R =正在运行,S =正在休眠,T =已停止,Z =僵尸(已终止,等待父级使用wait()
系统收集退出状态呼叫)。
使用此信息,系统知道何时返回ECHILD(不再有孩子)。
答案 1 :(得分:1)
内核为每个正在运行的进程维护一个数据结构。它还维护死亡但未被等待的进程(僵尸)的数据结构。父进程的数据结构有关于它还没有等待的孩子的信息(无论是僵尸还是还活着,僵尸的主要区别在于它们几乎没有肉体,即它们的数据结构只包含退出状态,资源使用,而不是更多,所以他们是非常重量级的。)