我一直在阅读有关 wait()
和 waitpid()
的文档,但我仍然对它们的工作方式有些困惑(我收集了 wait(&status)
等同于 waitpid(-1, &status, 0);
。下面是我正在处理的一些小代码片段。请帮助我了解这些片段是否编写正确,如果不正确,那是为什么。
目标 1:收割所有僵尸 child 。
int reapedPid;
do {
reapedPid = waitpid(-1,NULL,WNOHANG);
} while (reapedPid > 0);
我在这里尝试做的是遍历所有子节点,如果完成则收割子节点,如果没有完成则让它继续运行,当我用完子节点时 reapedPid == -1
并且循环退出。我在这里感到困惑的原因是我看不到 waitpid()
应该如何知道哪些 child 已经被检查过,哪些没有。它做任何这样的检查吗?还是这种方法行不通?
目标 2:等待所有 child 完成。
int pid;
do {
pid = wait(NULL);
} while (pid != -1);
在这里,我不关心子进程的结果状态是什么——这应该一直等待每个子进程完成,无论是成功还是失败,然后退出。我认为这段代码是正确的,但我不确定。
目标 3:fork 一个子进程并等待它完成。
int pid = fork();
if (pid < 0) {
// handle error.
}
else if (pid == 0) {
// execute child command
}
else {
int status;
int waitedForPid = waitpid(pid,&status,0);
assert(waitedForPid == pid);
}
在这里,我只是尝试 fork 进程并让父进程等待子进程完成。我不完全确定我是否应该在此处传递 0
选项,但似乎 WNOHANG、WUNTRACED 和 WCONTINUED 与我的目标并不真正相关。
最佳答案
跟踪进程是内核的工作。跟踪死进程是微不足道的。内核可以判断哪些子进程已死亡但尚未等待,并会在每次调用时返回其中一个已死亡的子进程,直到没有剩余可报告为止。 (由于
WNOHANG
选项,可能还有 child 要等待,但剩下的 child 还没有死。)第二个循环也很好,几乎等同于第一个。不同之处在于它会挂起等待所有 child 都死了再返回 -1。
第三个片段很好;除非在特殊情况下(例如程序中的另一个线程也在等待 child 并收集尸体),否则断言将为真。但是,如果您在某个地方启动了另一个进程并让它在后台运行,您可能正在收集僵尸,而通过修改其他循环,您可以收集僵尸并仍然等待正确的 child :
int pid = fork(); if (pid < 0) { // handle error. } else if (pid == 0) { // execute child command } else { int status; int corpse; while ((corpse = waitpid(-1, &status, 0)) > 0) if (corpse == pid) break; }
关于c - 等待 C 中的进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20062504/