为什么waitpid系统调用只能用于子进程?

为什么waitpid系统调用只能用于子进程?

手册页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)要高效得多。

相关内容