Process 监视进程是否已在C中终止 导言

Process 监视进程是否已在C中终止 导言,process,monitoring,c,fork,Process,Monitoring,C,Fork,我正在用C编写一个监控程序,它执行fork()和exec()循环。但是,我需要检查子进程是否在不阻塞主进程(即监控程序)的情况下终止。大概是这样的: 主要过程 我尝试过的 考虑到我有孩子,我尝试了以下方法: 用信号0发送kill呼叫并检查errno: if(kill(child|pid,0)=-1 | | errno==ESRCH),我认为这不是跟踪子进程状态的好方法,因为它不安全。此外,它并没有起作用,或者至少看起来是这样 使用stat(2)检查proc/child\u pid是否存在。在这

我正在用C编写一个监控程序,它执行
fork()
exec()
循环。但是,我需要检查子进程是否在不阻塞主进程(即监控程序)的情况下终止。大概是这样的:

主要过程

我尝试过的 考虑到我有孩子,我尝试了以下方法:

  • 信号0发送
    kill
    呼叫并检查
    errno

    if(kill(child|pid,0)=-1 | | errno==ESRCH)
    ,我认为这不是跟踪子进程状态的好方法,因为它不安全。此外,它并没有起作用,或者至少看起来是这样

  • 使用
    stat(2)
    检查
    proc/child\u pid
    是否存在。在这种情况下,上面所有的否定参数都是正确的,而且这种方法速度较慢

  • waitpid(2)
    。不幸的是,它阻碍了主要进程

问题
有没有其他办法获得这类信息?或者可能我在我已经尝试过的解决方案中遗漏了什么?

如果您将
WNOHANG
传递到
waitpid
,它应该不会阻塞

if(waitpid(child_pid, &status, WNOHANG) != 0) {
    // child process has finished
    foo();
} else {
    // child process still running
    bar();
}

当进程终止时,您可以设置父进程以获取和处理
SIGCHLD
信号,请参阅;信号处理程序只能调用异步信号安全函数,或在处理程序外部(例如,在主事件循环中…)或某些文件描述符(例如,管道或其他)设置测试的
volatile sigamatic\u t
标志。您也可以使用Linux特有的
signalfd

然后您可以使用一些等待功能,例如(如果您不想阻止,可以使用
WNOHANG
)或等待进程并获取其状态等


阅读更多。关于这些问题有几个章节。

< P>如果你希望你的进程不阻塞,或者你还有其他文件描述符来检查,那么你应该考虑系统调用,如果你正在为Linux编写。
此系统调用返回一个特殊的文件描述符,您可以在
select()
poll()
epoll()
系统调用中使用该描述符。如果设置正确,退出的子进程将导致内核使特殊文件描述符可读。从特殊文件描述符中读取将为您提供一个填充结构,其中包含有关子进程退出状态的信息。

Basile Starynkevitch的回答涵盖了最常见的情况

如果您有更多不寻常的情况,使用管道有时会很有用。在创建子进程之前,请使用
pipe
系统调用创建管道。创建子进程后,关闭父进程中管道的写入端。从管道读取数据将一直阻塞,直到子节点终止

这与
waitpid
的不同之处在于:

  • 从管道读取将等待子级及其所有子级终止(除非其中一些子级在此之前关闭文件描述符)
  • 可以从同一文件描述符读取多个进程,从而导致所有进程等待同一个进程(或多个进程)终止
  • 您不限于等待孩子终止。使用此方法,您还可以等待父级或同级终止
  • 通过使用close-on-exec,您可以等待进程终止或成功执行
    execve
    系统调用
  • 您可以在管道上使用
    select
    poll
    系统调用以及其他文件描述符

kill
ing一个带有任何信号的
child\u pid
是完全安全的竞争条件,只要你还没有收获(=等待)子进程,但是用零杀死不是确定进程是否死亡的好方法。重复杀死你的僵尸孩子是完全可以接受的,你不会得到任何ESRCH错误,直到你等待,这时比赛条件来了。
if(waitpid(child_pid, &status, WNOHANG) != 0) {
    // child process has finished
    foo();
} else {
    // child process still running
    bar();
}