【问题标题】:How to send a signal from the child process to parent process through kill command如何通过kill命令从子进程向父进程发送信号
【发布时间】:2019-06-02 06:24:29
【问题描述】:

我正在尝试通过fork() 系统调用创建一个子进程,然后尝试向父进程发送信号并在屏幕上打印出一些内容。

这是我的代码:-

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

void func1(int signum) {
    if(signum == SIGUSR2) {
        printf("Received sig from child\n");
    }
}

int main() {
    signal(SIGUSR2, func1);

    int c = fork();
    if(c > 0) {
        printf("parent\n");
    }
    else if(c == -1) {
        printf("No child");
    }
    else {
        kill(getppid(), SIGUSR2);
        printf("child\n");
    }

}

当我执行我的程序时,我得到的只是:-

child
Segmentation fault (core dumped)

我是 C 语言系统调用的新手,不明白为什么会发生这种情况,以及如何获得所需的输出,即打印所有三个 printf 语句。任何相同的帮助将不胜感激。

【问题讨论】:

  • c 应该是 pid_t 而不是 int 并且父进程也不会一直等待信号
  • 从信号处理程序中调用printf() 是不安全的。每footnote 188 of the C standard:“因此,信号处理程序通常不能调用标准库函数。” POSIX 允许使用信号处理程序调用异步信号安全函数。 printf() 不是异步信号安全的。
  • @firstlegagain1 我并不是说它正在完全运行,只是指出它可以在孩子尝试发送信号之前退出
  • 用你从答案中学到的东西来改变你的问题被认为是不好的做法,因为这样答案和 cmets 不再有意义:你添加了else if(c == -1)
  • 您是否(重新)编译和测试了您发布的代码?尽管存在一些问题,但很难看出这会导致段错误。

标签: c operating-system signals system-calls


【解决方案1】:

您的代码有许多小问题,并且肯定有未定义的行为,即您不能从信号处理程序调用 printf 或其他异步信号不安全函数。 这是带有修复的代码(参见代码中的 cmets)。这应该按预期工作(没有特定的打印语句顺序)并查看此代码是否仍然出现段错误。

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

void func1(int signum)
{
    /* write is asyc-signal-safe */
    write(1, "Received sig from child\n", sizeof "Received sig from child\n" - 1);
}

int main()
{
    signal(SIGUSR2, func1);

    /* fork returns a pid_t */
    pid_t c = fork();
    if(c > 0) {
        printf("parent\n");
        /* Wait for the child to exit; otherwise, you may not receive the signal */
        if (wait(NULL) == -1) {
            printf("wait(2) failed\n");
            exit(1);
        }
    } else if (c == -1) {
        printf("fork(2) error\n");
        exit(1);
    } else {
        if (kill(getppid(), SIGUSR2) == -1) {
            /* In case kill fails to send signal... */
            printf("kill(2) failed\n");
            exit(1);
        }
        printf("child\n");
    }
}

【讨论】:

  • 这里的关键是调用等待,如果你不这样做,你的父进程几乎肯定会在孩子尝试发送信号时终止,在 Unix 上你会结束up 试图向 init 进程发出信号。见stackoverflow.com/questions/15183427/…
  • 所以,我尝试了这个,它成功了。诀窍是信号处理程序中的 write 而不是 printf。当我删除它时,我的原始代码也可以正常工作
猜你喜欢
  • 1970-01-01
  • 2019-12-28
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多