【问题标题】:fork and signal: how to send signals from parent process to specific child processfork 和 signal:如何将信号从父进程发送到特定的子进程
【发布时间】: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() 的未定义行为。
  • @EOF 那我该怎么办?
  • @alk 但我仍然不知道如何向子进程发送信号。
  • kill() 系统调用是您所需要的。棘手的部分是您必须以某种方式告诉每个孩子其兄弟姐妹的 PID。也许父母通过在管道上写信息来告诉他们两个?或者,也许您使用进程组来发出信号。

标签: c linux signals fork kill


【解决方案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() 时,子进程是父进程的副本。这包括全局变量和局部变量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 2019-04-11
    • 1970-01-01
    相关资源
    最近更新 更多