【问题标题】:Check whether Child Process has terminated in C on Unix without blocking检查子进程是否已在 Unix 上以 C 终止而不阻塞
【发布时间】:2020-08-27 12:32:11
【问题描述】:

我想检查子进程是否/何时在 Unix 上的 C 中终止。它不应该阻塞,而是循环中的简短检查。 我的代码:

pid_t pid = fork();
if (pid > 0)
    // Parent Process
    while (1) {
        // Do a short check whether Child has already terminated if yes break the loop.
    // Ik that it's possible to use waitpid(pid, &status, 0) but that blocks the whole loop until the child has terminated 

    }
if (pid == 0)
    printf("child process born");
    exit(0);

提前谢谢

【问题讨论】:

  • 乍一看,pid = 0 的分配看起来很奇怪。

标签: c unix process fork parent


【解决方案1】:

waitpid 的第三个参数是一组标志。如果您将WNOHANG 传递给此参数,则如果没有子级尚未退出,该函数将立即返回。

然后您可以检查 waitpid 是否返回 0。如果是,则没有子退出,您等待并重试。

while (1) {
    pid_t rval = waitpid(pid, &status, WNOHANG);

    if (rval == -1) {
        perror("waitpid failed");
        exit(1);
    } else if (rval == 0) {
        sleep(1);
    } else {
        break;
    }
}

【讨论】:

  • waitpid(..., WNOHANG) 因为没有子节点退出而立即返回时,它不会向status 写入有意义的值。您的示例代码应在查看status 之前检查rval > 0(可能返回-1 或0,表示没有可报告的状态更改,请参阅pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html 返回值部分)。
  • 此外,在某些情况下,waitpid 报告说孩子患有某些疾病,但 WIFEXITED(status)WIFSIGNALED(status) 都不是真的。
  • @zwol 应该更仔细地阅读文档...已修复。
  • 为了减少延迟,您可以线程化 waitpid 并通过原子布尔值与循环通信。检查布尔值比系统调用快得多。
【解决方案2】:

传统方式是:

#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

int exist(pid_t pid) {
   return kill(pid, 0) > 0 || errno != ESRCH;
}
int main(int ac, char **av) {
    while (--ac > 0) {
        pid_t p = strtol(*++av, 0, 0);
        printf("%d %s\n", p, exist(p) ? "exists" : "doesn't exist");
    }
    return 0;
}

它不关心 parent : child 关系(而 wait 派生类关心),即使您没有影响进程的权限也可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多