如何等待退出非子进程

问题描述 投票:29回答:8

对于子进程,wait()waitpid()函数可用于暂停当前进程的执行,直到子进程退出。但是此功能不能用于非子进程。

还有其他功能,可以等待退出任何进程吗?

c linux process wait
8个回答
25
投票

什么都不等于wait()。通常的做法是使用kill(pid, 0)进行民意调查,并查找errno的返回值-1和ESRCH,以表明该过程已经消失。


13
投票

在BSD和OS X上,您可以使用带有EVFILT_PROC + NOTE_EXIT的kqueue来完成该操作。不需要投票。不幸的是,没有Linux等价物。


10
投票

到目前为止,我已经在Linux上找到了三种方法:

  • 轮询:你经常检查过程的存在,通过使用kill或测试/proc/$pid的存在,就像在大多数其他答案中一样
  • 使用ptrace系统调用作为调试器附加到进程,以便在退出时收到通知,如a3nm's answer
  • 使用netlink接口来监听PROC_EVENT_EXIT消息 - 这样每次进程退出时内核都会告诉您的程序,而您只是等待正确的进程ID。我只看到过这个描述的in one place on the internet

无耻的插件:我正在开发一个program(当然是开源的; GPLv2),它可以完成三个中的任何一个。


5
投票

您还可以创建套接字或FIFO并读取它们。 FIFO特别简单:将您孩子的标准输出连接到FIFO并读取。读取将阻止,直到子进程退出(出于任何原因)或直到它发出一些数据。因此,您需要一个小循环来丢弃不需要的文本数据。

如果您可以访问子项的源,请在启动时打开FIFO进行写入,然后将其忘记。当子进程终止并且等待的“父”进程将被唤醒时,操作系统将清除打开的文件描述符。

现在这可能是一个你没有开始或拥有的过程。在这种情况下,您可以使用启动实际二进制文件的脚本替换二进制可执行文件,但也可以添加监视,如上所述。


3
投票

你可以用ptrace(2)附加到这个过程。从壳,strace -p PID >/dev/null 2>&1似乎工作。这可以避免繁忙等待,但它会减慢跟踪过程的速度,并且不会对所有进程起作用(只有你的进程,这比只有子进程好一点)。


2
投票

没有我知道。除了混乱的解决方案,如果你可以改变你想要等待的程序,你可以使用信号量。

图书馆的功能是qazxsw poi,qazxsw poi qazxsw poi ...

sem_open(3)执行等待,所以你不必像在混乱的解决方案中那样忙着等待。当然,使用信号量会使您的程序更加复杂,并且可能不值得麻烦。


1
投票

也许有可能等待/ proc / [pid]或/ proc / [pid] / [something]消失?

有poll()和其他文件事件等待函数,也许这可能会有所帮助?


1
投票

这是一种在没有轮询的情况下等待linux中的任何进程(不一定是子进程)退出(或被杀)的方法:

使用inotify等待删除/ proc'pid'将是完美的解决方案,但遗憾的是inotify不适用于像/ proc这样的伪文件系统。但是我们可以将它与进程的可执行文件一起使用。虽然该过程仍然存在,但此文件仍处于打开状态。因此我们可以使用in_ify与IN_CLOSE_NOWRITE来阻止,直到文件关闭。当然,它可以因其他原因而关闭(例如,如果具有相同可执行文件的另一个进程退出),那么我们必须通过其他方式过滤这些事件。

我们可以使用kill(pid,0),但这不能保证它是否仍然是相同的进程。如果我们对此真的很偏执,我们可以做点别的事。

这是一种100%安全的方式来防止pid重用问题:我们打开伪目录/ proc /'pid',并保持打开直到我们完成。如果同时使用相同的pid创建新进程,则我们保留的目录文件描述符仍将引用原始进程(或者如果旧进程不再存在则变为无效),但绝不会引用新进程重复使用的pid。然后我们可以检查原始进程是否仍然存在,例如,检查文件“cmdline”是否存在于openat()目录中。当进程退出或被杀死时,这些伪文件也不再存在,因此openat()将失败。

这是一个示例代码:

sem_init(3),
© www.soinside.com 2019 - 2024. All rights reserved.