在UNIX環境中高級編程的第9.6節,我們可以讀到:shell/kernel如何處理信號發送到同一進程組中的進程?
當我們按下終端的中斷鍵(通常是DELETE或Control-C),中斷信號被髮送到所有進程前臺進程組。
我寫超級簡單的Python腳本,處理SIGINT信號和比較結果做了一個簡單的測試:
#!/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
,並確保過程在同一個過程組中:
$ 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信號之後,每個進程都應該接收到信號並使用處理程序處理它。 可悲的是,這種情況並非如此:
如果我將信號發送到進程組組長(PID 9702在這種情況下),所有的進程都將終止,但我只能看到進程組組長調用信號處理函數(如處理程序調用執行路徑只創建一個文件)
如果我將信號發送到過程,是不進程組創建者,該過程將退出,處理信號,從處理之後創建的相同管道(進程組)也將「靜默」終止。
$ 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
我想明白爲什麼這裏的行爲是不對準什麼在書中被描述(屬於同一進程組的所有進程終止在發送信號到其中的任何)。特別是信號如何傳送到多個進程,但並非所有的信號處理程序都被調用。謝謝你的解釋。
'按終端的中斷鍵'與通過'kill'或其他方式發送信號**不一樣**。在運行可執行文件的同一終端中按「Ctrl + C」。 – Tsyvarev
我知道它會使所有的過程變得複雜,但我的理解是CTRL-C只是向過程組發送信號的一種方式。 – Maro
'但我的理解是CTRL-C只是一種向過程組發送信號的方式。「 - 不,你錯了。它是終端的一個特性,它以特定的方式處理CTRL-C。例如,GUI應用程序不處理CTRL-C,但可以通過kill終止它們。 – Tsyvarev