手册页wait(2)
指出,如果指定的进程不是调用进程的子进程,则waitpid
系统调用将返回错误。ECHILD
为什么是这样?等待非子进程会产生某种安全问题吗?是否有技术原因导致实现非子进程的等待会很困难或不可能?
答案1
因为如何waitpid
运作。在 POSIX 系统上,当父进程的一个子进程终止时,会向其传递一个信号 (SIGCHLD)。在较高级别上,waitpid
所做的一切都是阻塞,直到为指定的进程(或进程之一)传递 SIGCHLD 信号为止。您不能等待任意进程,因为永远不会为它们传递 SIGCHLD 信号。
答案2
godlygeek 的答案有助于理解系统如何工作,但不可避免地随之而来的问题是:
如何判断一个进程是否已经消失?
等待另一个进程组或会话中的进程的正确方法是使用kill()
。显然,这是一个不直观的答案。您不能使用该wait
函数系列,因为 SIGCHILD 信号永远不会传递到您的进程,也无法获取状态代码。 kill()
但是,可以通过传入 0 作为要发送的信号来告诉您特定进程何时消失,这只是检查是否可以向该进程发送信号。的返回值kill()
很复杂,但可以归结为:值 0 表示进程处于活动状态,并将接受来自您的进程的信号,而值 -1 和 errno EPERM 表示进程处于活动状态,但不接受来自您的进程的信号过程。
一些示例 C 代码每秒检查一次以查看任意进程是否消失:
int res = kill(pid, 0);
while (res == 0 || (res < 0 && errno == EPERM))
{
sleep(1);
res = kill(pid, 0);
}
您可以类似地尝试以下kill
命令:
kill -0 <pid>
这会将 pid 和 0 传递到kill()
.有些 shell 具有内置的kill
,因此它比启动新进程(例如ps
)要高效得多。