0x4*_*450 7 c monitoring fork process
我正在用C编写一个监控程序,它执行fork()
和exec()
循环.但是,我需要在不阻塞主进程(即监视程序)的情况下检查子进程是否已终止.像这样的东西:
主要过程
pid_t child_pid = fork();
if (child_pid == 0)
exec(bar);
while (1) {
if (the child process has finished)
foo();
else
bar();
}
Run Code Online (Sandbox Code Playgroud)
考虑到我有孩子pid的事实,我尝试了以下方法:
发送kill
电话signal 0
并进行检查errno
:
if (kill(child_pid, 0) == -1 || errno == ESRCH)
我认为这不是跟踪儿童过程状态的好方法,因为它不受种族条件的影响.此外它没有用,或者至少看起来如此.
检查stat(2)
是否proc/child_pid
存在.在这种情况下,所有上述否定参数都是正确的,并且此方法较慢.
waitpid(2)
.不幸的是,它阻碍了主要过程.
有没有其他方法可以获得这种信息?或者也许我错过了我已经尝试过的解决方案?
Eri*_*ouf 13
如果你传递WNOHANG
给waitpid
它不应该阻止.
if(waitpid(child_pid, &status, WNOHANG) != 0) {
// child process has finished
foo();
} else {
// child process still running
bar();
}
Run Code Online (Sandbox Code Playgroud)
Bas*_*tch 11
当一个进程终止时,你可以设置父进程来获取和处理一个SIGCHLD
信号,参见signal(7) ; 信号处理程序只能调用异步信号安全函数,或设置volatile sigatomic_t
在处理程序外测试的标志(例如在poll(2)周围的主事件循环中...),或者将(2)写入某个文件描述符(例如管道或某个eventfd(2)).正如Bruce Ediger所说,你也可以使用特定于Linux的signalfd
.
然后你可以使用一些等待函数,例如waitpid(2)(WNOHANG
如果你不想阻止)或者wait4(2)等待进程并获得它的状态等.
另请参阅高级Linux编程.它有几个关于这些问题的章节.
如果你希望你的过程中不堵塞,或者你已经有了其他文件描述符来检查了,你应该考虑signalfd()如果你正在写的Linux系统调用.
这个系统调用给回一个特殊的文件描述符,你可以在使用select()
,poll()
并且epoll()
系统调用.正确设置,子进程退出会导致内核生成特殊文件描述符readabl.从特殊文件描述符中读取会为您提供一个填充结构,其中包含有关子进程退出状态的信息.
Basile Starynkevitch的答案涵盖了最常见的情况.
如果您有更多不寻常的情况,有时使用管道是有用的.在创建子进程之前,使用pipe
系统调用创建管道.创建子进程后,关闭父进程中管道的写入结束.从管道读取将阻止直到孩子终止.
这与waitpid
以下方式不同:
execve
系统调用.select
或poll
系统调用以及其他文件描述符.