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

Monitor if a process has terminated in C

简介

我正在用 C 编写一个监控程序,它执行 fork()exec() 循环。但是我需要检查 child 进程是否已经终止而不阻塞主进程,即监控程序。像这样:

主要流程

pid_t child_pid = fork();
if (child_pid == 0)
    exec(bar);

while (1) {
    if (the child process has finished)
        foo();
    else
        bar();
}

我试过的

考虑到我有 child pid 的事实,我尝试了以下操作:

问题

请问还有其他途径获取此类信息吗?或者我可能遗漏了一些我已经尝试过的解决方案?

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

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

当进程终止时,您可以设置父进程来获取和处理 SIGCHLD 信号,参见 signal(7); the signal handler can only call async-signal-safe functions, or set a volatile sigatomic_t flag tested outside of the handler (e.g. in your main event loop around poll(2)...), or write(2) to some file descriptor (e.g. a pipe or some eventfd(2)). As 您也可以使用 Linux-specific signalfd.

然后你可以使用一些等待功能,例如waitpid(2) (perhaps with WNOHANG if you don't want to block) or wait4(2)等待进程并获取其状态等

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

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

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

Basile Starynkevitch 的回答涵盖了大多数常见情况。

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

这与 waitpid 在以下方面有所不同:

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