fork()以及如何将信号传递到流程


Answers:


20

我们为什么不试试看呢?这是一个微不足道的程序,signal(3)用于捕获SIGINT父进程和子进程,并在消息到达时打印出标识该进程的消息。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void parent_trap(int sig) {fprintf(stderr, "They got back together!\n");}
void child_trap(int sig) {fprintf(stderr, "Caught signal in CHILD.\n");}
int main(int argc, char **argv) {
    if (!fork()) {
        signal(SIGINT, &child_trap);
        sleep(1000);
        exit(0);
    }
    signal(SIGINT, &parent_trap);
    sleep(1000);
    return 0;
}

让我们称之为test.c。现在我们可以运行它:

$ gcc test.c
$ ./a.out
^CCaught signal in CHILD.
They got back together!

终端中生成的中断信号将传递到活动进程组,该进程组在此既包括父进程,也包括子进程。当我按- 时,您可以看到child_trapparent_trap都已执行。CtrlC

在POSIX中fork和信号之间的交互进行冗长的讨论。这里最重要的部分是:

在fork()之后发送到进程组的信号应同时传递给父级和子级。

他们还注意到,某些系统可能无法以完全正确的方式运行,特别是当信号到达的时间非常接近的时间时fork()。弄清楚您是否使用这些系统之一,可能需要阅读代码或非常幸运,因为每次单独尝试的交互都几乎不会消失。

其他有用的点是:

  • 一种信号手动生成和发送到单个过程(可能kill)将被递送到该过程中,无论它是否是父或子。
  • 信号处理程序在进程之间运行的顺序未定义,因此您不能依赖任何一个先执行。
  • 如果定义中断处理程序(或显式忽略信号),则两个进程都将退出并带有SIGINT代码(默认行为)。
  • 如果一个人非致命地处理信号,而另一个人则不处理,那么一个没有处理程序的人将死亡,另一个会继续。

我认为炮弹也会以有趣的方式干扰吗?如果这是他们可以捕获的信号,则可能会将其发送给其子级?(然后是SIGHUP)(所有这些可能都意味着,尽管OS不发送信号,但是子进程可能不会受到发给父进程的信号的影响……)
Gert van den Berg
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.