2016-09-26 149 views
2

在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信號之後,每個進程都應該接收到信號並使用處理程序處理它。 可悲的是,這種情況並非如此:

  1. 如果我將信號發送到進程組組長(PID 9702在這種情況下),所有的進程都將終止,但我只能看到進程組組長調用信號處理函數(如處理程序調用執行路徑只創建一個文件)

  2. 如果我將信號發送到過程,是進程組創建者,該過程將退出,處理信號,從處理之後創建的相同管道(進程組)也將「靜默」終止。

    $ 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 
    

我想明白爲什麼這裏的行爲是不對準什麼在書中被描述(屬於同一進程組的所有進程終止在發送信號到其中的任何)。特別是信號如何傳送到多個進程,但並非所有的信號處理程序都被調用。謝謝你的解釋。

+0

'按終端的中斷鍵'與通過'kill'或其他方式發送信號**不一樣**。在運行可執行文件的同一終端中按「Ctrl + C」。 – Tsyvarev

+0

我知道它會使所有的過程變得複雜,但我的理解是CTRL-C只是向過程組發送信號的一種方式。 – Maro

+1

'但我的理解是CTRL-C只是一種向過程組發送信號的方式。「 - 不,你錯了。它是終端的一個特性,它以特定的方式處理CTRL-C。例如,GUI應用程序不處理CTRL-C,但可以通過kill終止它們。 – Tsyvarev

回答

1

看起來像我想出來的。我的理解是,CTRL-C只會將SIGINT信號發送給進程羣組領導,但看起來這更復雜,並且shell將負責發送信號給進程組中的每個進程。

在我的測試中,爲什麼信號處理程序被稱爲只有一個的原因是其他進程正在退出正確。在致電proc1 | proc2 | proc3和殺害,說proc1,它正在處理信號和proc2和proc在輸入關閉時退出。在for循環之後添加測試睡眠()會顯示如果殺死proc1,其餘進程仍然存在。

相關問題