【问题标题】:Monitor if a process has terminated in C监视进程是否已在 C 中终止
【发布时间】:2015-10-18 07:24:17
【问题描述】:

简介

我正在用 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,我尝试了以下方法:

  • 使用signal 0 发送kill 呼叫并检查errno

    if (kill(child_pid, 0) == -1 || errno == ESRCH),我认为这不是跟踪子进程状态的好方法,因为它在竞争条件下并不安全。此外,它不起作用,或者至少看起来如此。

  • 使用stat(2) 检查proc/child_pid 是否存在。在这种情况下,上述所有否定论点也是正确的,而且这种方法速度较慢。

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

问题

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

【问题讨论】:

  • killing a child_pid 只要你还没有收获(=等待)孩子,任何信号都是完全安全的,但是用零杀死不是确定进程是否死亡的好方法。反复杀死你的僵尸孩子是完全可以接受的,直到你wait,你才会得到任何 ESRCH 错误,此时比赛条件来了。

标签: process monitoring c fork


【解决方案1】:

如果您将WNOHANG 传递给waitpid,它不应阻塞。

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

【讨论】:

    【解决方案2】:

    当进程终止时,可以设置父进程获取并处理SIGCHLD信号,见signal(7);信号处理程序只能调用异步信号安全函数,或设置一个在处理程序外部测试的volatile sigatomic_t 标志(例如在您的主事件循环中围绕poll(2)...),或write(2) 到某个文件描述符(例如管道或一些eventfd(2))。作为Bruce Ediger answered,您还可以使用Linux 特定的signalfd

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

    另请阅读Advanced Linux Programming 了解更多信息。它有几个章节讨论这些问题。

    【讨论】:

      【解决方案3】:

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

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

      这在以下方面与waitpid 不同:

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

      【讨论】:

        【解决方案4】:

        如果您希望您的进程不阻塞,或者您可能需要检查其他文件描述符,那么如果您正在为 Linux 编写代码,则应该考虑使用 signalfd() 系统调用。

        此系统调用返回一个特殊的文件描述符,您可以在select()poll()epoll() 系统调用中使用它。正确设置,退出的子进程会导致内核使特殊文件描述符可读。从特殊文件描述符中读取会为您提供一个填充结构,其中包含有关子进程退出状态的信息。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-29
          • 1970-01-01
          • 2022-01-19
          • 2011-07-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多