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