shell/内核如何处理发送到同一进程组内的进程的信号?

UNIX环境高级编程的 9.6节中,我们可以读到:

每当我们按下terminal的中断键(通常是DELETE或Control-C),中断信号就会发送到前台进程组中的所有进程。

我通过编写超级简单的Python脚本,处理sigint信号和比较结果做了一个简单的testing:

#!/usr/bin/python3 import os import sys import signal def handler(signum, frame): p = os.getpid() with open(str(p), 'w+') as fh: fh.write("Received signal at pid: {0}".format(os.getpid())) raise SystemError() def main(): signal.signal(signal.SIGINT, handler) for line in sys.stdin: print("READ {0}".format(line.rstrip('\n'))) main() 

我简单地运行它,如下所示:

 $ ./reader.py | ./reader.py | ./reader.py 

并确保stream程在同一个stream程组中:

 $ ps -ae pid,ppid,pgid,sess,comm $ PID PPID PGID SESS COMMAND 9702 5930 9702 5930 reader.py 9703 5930 9702 5930 reader.py 9704 5930 9702 5930 reader.py 

我的理解是,我发送一个INT信号到任何进程后,每个应该接收到的信号和处理程序处理。 可悲的是,事实并非如此:

  1. 如果我将信号发送给进程组组长(本例中为pid 9702),则所有进程都将终止,但是我只能看到进程组首部调用信号处理函数(只有一个文件被创build为处理程序调用执行path)

  2. 如果我将信号发送到不是进程组组长的进程,进程将退出,处理信号,同一pipe道(进程组)中的进程将被“静默”终止。

      $ ps -ao pid,ppid,pgid,sess,comm PID PPID PGID SESS COMMAND 9842 5930 9842 5930 reader.py 9843 5930 9842 5930 reader.py 9844 5930 9842 5930 reader.py $kill -INT 9843 $ ps -ao pid,ppid,pgid,sess,comm PID PPID PGID SESS COMMAND 1456 1446 1456 1446 weechat 5893 5873 5893 5873 screen 5928 5902 5928 5902 screen 9842 5930 9842 5930 reader.py 

我想了解为什么这里的行为不符合本书所描述的内容(属于同一个进程组的所有进程在发送信号给它们之后都会终止)。 特别是信号如何传递到多个进程,但并不是所有的信号处理程序都被调用。 感谢您的解释。

看起来像我想出来的。 我的理解是,CTRL-C只会将SIGINT信号发送给进程群组领导,但是看起来像这样更加复杂,并且shell将负责发送信号给进程组中的每个进程。

在我的测试中,为什么信号处理程序被称为只有一个的原因是其他进程正在退出正确。 在调用proc1 |之后 proc2 | proc3和杀死,说proc1,它正在处理信号和proc2和proc在输入关闭时退出。 在for循环之后添加测试睡眠()会显示如果我终止proc1,剩下的进程将仍然活着。