![fork() 以及信号如何传递到进程](https://linux22.com/image/35299/fork()%20%E4%BB%A5%E5%8F%8A%E4%BF%A1%E5%8F%B7%E5%A6%82%E4%BD%95%E4%BC%A0%E9%80%92%E5%88%B0%E8%BF%9B%E7%A8%8B.png)
我用 C fork() 编写的程序关闭了子进程。两个进程都不会终止。如果我从命令行启动程序并按 control-c 哪个进程将收到中断信号?
答案1
我们为什么不尝试一下呢?这是一个简单的程序,使用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_trap
和parent_trap
Ctrl当我按下-时被处决C。
有一个对之间的相互作用进行冗长的讨论fork
POSIX 中 和 信号。这里最重要的部分是:
在 fork() 之后发送到进程组的信号应该传递给父进程和子进程。
他们还指出,某些系统可能不会以完全正确的方式运行,特别是当信号到达的时间非常接近时fork()
。弄清楚您是否在其中一个系统上可能需要阅读代码或需要很大的运气,因为在每次单独的尝试中交互几乎不可能发生。
其他有用的点是:
- 手动生成并发送到单个进程的信号(可能带有
kill
) 会被交付仅有的到该进程,无论它是父进程还是子进程。 - 信号处理程序在进程之间运行的顺序未定义,因此您不能依赖其中任何一个先执行。
- 如果你不定义一个中断处理程序(或显式忽略信号),两个进程都会以
SIGINT
代码退出(默认行为)。 - 如果其中一个非致命地处理信号而另一个没有处理,则没有处理程序的一个将死亡,而另一个将继续。