fork 和 signal:如何将信号从父进程发送到特定的子进程

Posted

技术标签:

【中文标题】fork 和 signal:如何将信号从父进程发送到特定的子进程【英文标题】:fork and signal: how to send signals from parent process to specific child process 【发布时间】:2017-01-09 13:43:50 【问题描述】:

我需要fork 两个子进程。一个可以接收信号3,打印hello并将信号4发送给另一个子进程;另一个可以接收信号4,打印world并将信号3发送给第一个子进程。 启动时,父进程会在休眠 3 秒后向第一个子进程发送信号 3。 然后 3 秒后,父进程会发送SIGKILL 杀死他们两个。

我不知道如何向特定的子进程发送信号(我知道我们有一个函数kill 可以发送信号,但我不知道在这里使用它)。

这是我的代码:

#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>

void func(int n)

        printf("ping\n");
        // how to send signal 4 to the second process?


void func2(int n)

        printf("pong\n");
        // how to send signal 3 to the first process?


int main()

        pid_t pid;
        int i;
        for(i = 0; i < 2; i++)
        
                pid = fork();
                if(pid == 0)
                
                        if(i == 0)
                        
                                signal(3, func);
                        
                        else
                        
                                signal(4, func2);
                        
                        while(1);
                
                else
                
                        if(i == 1)
                        
                                sleep(3);
                                // how to send signal 3 to the first child process?
                                sleep(3);
                                // how to kill the two children?
                        
                
        


        return 0;

【问题讨论】:

在信号上下文中调用 printf() 的未定义行为。 man7.org/linux/man-pages/man2/kill.2.html @EOF 那我该怎么办? @alk 但我仍然不知道如何向子进程发送信号。 kill() 系统调用是您所需要的。棘手的部分是您必须以某种方式告诉每个孩子其兄弟姐妹的 PID。也许父母通过在管道上写信息来告诉他们两个?或者,也许您使用进程组来发出信号。 【参考方案1】:

您可以使用 popen() 函数通过分叉并打开通往该进程的管道来打开该进程(而不是直接使用 fork())

父进程知道每个进程的 PID,因此可以轻松地将第二个子进程的 pid 传递给第一个子进程。

第一个孩子可以使用 pid 和 kill()` 函数将信号传递给第二个孩子。

所以,使用 popen() 启动第一个孩子。使用 fork() 启动第二个孩子,然后通过使用 popen() 创建的流将 pid 从第二个孩子传递给第一个孩子。

没有正确处理从调用 fork() 返回的 pid 值。

发布的代码假设对 fork() 的调用是成功的......这不是一个安全/有效的假设

代码还需要检查 pid 是否为 -1 并适当地处理该错误。

当子进程完成时,它不应该处于while() 循环中,而是应该退出,使用exit() 函数。

父进程不应该只是退出,因为这会使两个子进程成为僵尸进程。 (没有系统重启,僵尸很难摆脱。)

相反,父进程应该调用wait() 甚至更好的waitpid()(并记住子进程需要实际退出,而不是坐在while() 循环中。

1) func()func2() 应该检查参数以确保它是正在处理的正确信号。

2) signal() 的手册页表明不应使用它。手册页建议使用:sigaction(),

【讨论】:

【参考方案2】:

当您 fork 时,您将获得新的 pid。根据kill manpage,您使用pid 调用kill(pid_t pid, int sig);

【讨论】:

如果我在第一个sleep(3) 之后写kill(pid, 3),我认为它会发送给所有子进程。我需要的是发送到第一个子进程。 @Thomas:不;除非您对pid 使用零或负值,否则它将信号发送到一个进程。 好的。我得到了它。我还有一个问题:如何在进程之间共享 pid?因为我需要在func 中输入kill(4, secondProcessPid) 和在func2 中的kill(3, firstProcessPid)。如何获得这两个pid?我必须使用共享内存之类的东西吗? 您对kill 的论点倒退了......在这种情况下,共享内存似乎有点过分了。当您fork() 时,子进程是父进程的副本。这包括全局变量和局部变量。

以上是关于fork 和 signal:如何将信号从父进程发送到特定的子进程的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 python 信号在独立进程之间发送消息?

向父母发送信号不起作用

信号发送到 PGRP

signal信号

Python和Signal

Python模块之信号学习(signal)