监控进程是否已在C

时间:2015-07-27 16:36:25

标签: process monitoring c fork

简介

我正在用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)。不幸的是,它阻碍了主要过程。

问题

有没有其他方法可以获得此类信息?或许我错过了我已经尝试过的解决方案中的一些东西?

4 个答案:

答案 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的不同之处在于:

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