c - 如何获取已死亡子进程的 PID 并在父进程中使用它?

标签 c unix fork freebsd sigchld

我正在尝试编写一个 C 程序(适用于 FreeBSD、Unix),它在循环中创建 4 个子进程。每个 child 都会做事,当他们死后,他们会立即被其他 child 取代。所以,最后我有4个 child 一直在工作。

每个子 PID 都必须注册在一个表中,当它们死亡后,表中的 PID 必须被删除。这是我遇到麻烦的部分。

因此,在第一次尝试中,我尝试创建一个处理程序,将死亡 child 的 PID 发送到全局变量:

int global_variable;

void handler_SIGCHLD(int sig)
{
    pid_t son;
    int e;

    do {
        son = wait3(&e, WNOHANG, NULL);
        if ((son > (pid_t)0) && (WIFEXITED(e) || WIFSIGNALED(e)))
        {
            global_variable = son;
        }
    } while (son > (pid_t)0);
}

然后我在父级中使用它从表中删除已死亡子级的 PID。但后来我意识到,如果两个 child 同时死亡,其中一个 PID 将被另一个覆盖。

如何避免这种情况?

最佳答案

您不应该从信号处理程序中执行此操作。您不应该从信号处理程序中执行任何操作(如果您希望保持理智)。

可靠的方法是将 SIGCHLD 信号转换为文件描述符事件,然后将其集成到事件循环中(selectpollepoll...)。当您观察一个事件时,您可以在循环中使用 waitpid(..., WNOHANG) 来收集所有死去的 child 。在这里查看我的答案的更多信息:https://stackoverflow.com/a/8398491/1020667

以上答案假设您使用的是 Linux 并使用 signalfd (Linux 特定工具)将信号转换为文件描述符。但是,您也可以使用“自管道”技巧(非常小心)或kqueue(FreeBSD、OSX)。请注意,使用kqueue,没有中间文件描述符,您可以像文件描述符事件一样直接接收信号事件。

另一方面,您可以通过使用可移植事件循环库来解决所有这些低级细节。一些库已经提供了启动和监视子进程的工具。我推荐(node.js 的)libuv。

关于c - 如何获取已死亡子进程的 PID 并在父进程中使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26827230/

相关文章:

c - 与 C 信号的简单同步

linux - 如何在linux中检查 'if-then-else-fi'中的多个字符串?

c++ - 如何使 boost asio 前叉安全

c++ - 使用 fork() 创建多个进程,无需使用 exit() 或 wait() 即可与管道通信

c - fork() 这个图我看不懂

c - 编写一个程序来打印 zigzagarray 中的数组元素

header 可以使用源文件中定义的宏定义吗?

c - C 中使用的括号,不带 if、循环等控制结构

linux - 用环境变量替换curl请求中的变量

bash - 在不排序的情况下删除变量上的重复项