waitpid、wnohang和wuntraced是UNIX系统编程中与进程管理相关的函数参数。 waitpid用于等待指定进程的结束,wnohang表示在没有子进程结束时立即返回,wuntraced表示不追踪已结束但尚未被处理的子进程。例如: ``` waitpid(pid, &status, WNOHANG|WUNTRACED) ``` 这个调用会等待pid指定的进程结束,如果该进程还没有结束,则立即返回0;并且不会追踪已结束但尚未被处理的子进程。

41

我有些困惑。据我所知,waitpid使用pid为-1的选项意味着我等待所有子进程结束,但如果我在waitpid中添加WNOHANG选项,则该选项表示如果没有任何子进程结束就立即退出……这似乎非常令人困惑。

我为什么要告诉计算机等待子进程完成然后立即告诉它如果没有任何子进程完成就立即退出呢?

有人可以解释一下这个选项和WUNTRACED选项吗?我不知道什么是被跟踪的意思。


1
pid = -1 表示等待 任何 子进程,而不是所有子进程。而 "wait" 是一个技术术语,指的是 wait(2) - melpomene
@melpomene 啊,没错,任何和所有确实非常不同。谢谢纠正。比如我有三个孩子……电脑是如何确定要等待哪一个呢?还是说这是一种先到先得的方式,如果其中一个孩子完成了,那么电脑就已经等待过了并继续执行下去了? - 8this
如果传递了一个pid为-1,它不会等待所有子进程完成,而是等待任何一个子进程完成。一旦有任何一个子进程完成,它就被回收了。 - fuz
2个回答

100

通常情况下,你会在不同的情况下使用WNOHANG和WUNTRACED。

情况1:假设你有一个进程会生成许多子进程,并需要在子进程运行时执行其他任务。这些子进程有时会退出或被杀死,但内核会保留其退出状态,直到其他进程通过wait()或waitpid()来获取它们的退出状态。因此,父进程需要定期调用wait() / waitpid()来让内核清理掉已经死亡的子进程。但是我们不希望wait()/waitpid()被阻塞,因为在这种情况下,我们的进程需要执行其他任务。我们只希望收集已经dead的进程的状态,如果有的话。这就是WNOHANG的作用。它防止wait() / waitpid()阻塞以便您的进程可以继续进行其他任务。如果有子进程死亡,它的pid将通过wait() / waitpid()返回,然后您的进程可以对其进行处理。如果没有任何进程死亡,则返回的pid为0。

情况2:相反地,假设你的父进程在子进程运行时不想执行任何操作。你不想让它执行某些无用的循环,因此你使用一个不带WNOHANG参数的普通wait() / waitpid()。您的进程将从执行队列中移除,直到其中一个子进程死亡。但是,如果其中一个子进程因为收到SIGSTOP而被暂停了呢?你的子进程不再在处理你分配给它的任务,但父进程仍在等待。所以,在某种意义上,你陷入了一种死锁状态,除非该子进程通过父进程外部手段(如发送SIGCONT)继续运行。WUNTRACED允许您在子进程停止、退出或被杀死时从wait() / waitpid()返回父进程。这样,你就有机会发出SIGCONT来继续运行它,杀死它,将其任务分配给另一个子进程,或者进行其他操作。


7
传说级的解释! - Benny
默认情况下,wait()或waitpid()不会通知父进程子进程因信号而停止。因为文档中说“暂停调用线程的执行,直到其子进程之一终止”。所以我不清楚“终止”是否可能是由于信号引起的。 - tonythestark
2
啊,术语不是很清楚...是我的错。 "Terminated" 意味着进程已经完成(或由于故障崩溃或被 SIGKILL 杀死),并且有一个退出代码可供父进程检查。在我上面使用“stopped”的地方,我真的应该说“suspended”或“paused”(但执行此操作的信号是“SIGSTOP”,这就是为什么我变得懒惰并说“stopped”的原因)。挂起的进程(例如在 shell 中使用 Ctrl-z 时)可以稍后恢复。因此,任何时候进程终止(通过 exit(val)、SIGKILL、segfault)都应允许 wait() 继续。 - Jemenake

20
如果您传递-1WNOHANGwaitpid()将检查是否存在任何僵尸子进程。如果是,则收回其中一个并返回其退出状态。如果没有,则返回0(如果未终止的子进程存在)或返回-1(如果不存在),并将ERRNO设置为ECHILD(没有子进程)。如果您想找出您的任何子进程最近是否已死亡,而不必等待其中一个死亡,这非常有用。在这方面它非常有用。
选项WUNTRACED的文档如下,我对此描述没有任何补充:

WUNTRACED - 也报告由pid指定且已停止但其状态尚未报告的任何子进程的状态。

阅读POSIX中的waitpid页面以获取更多详细信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接