初步理解Python程式的訊號通訊

發表於2015-12-30

訊號的概念

訊號(signal     程式之間通訊的方式,是一種軟體中斷。一個程式一旦接收到訊號就會打斷原來的程式執行流程來處理訊號。

幾個常用訊號:

SIGINT     終止程式  中斷程式  (control+c)

SIGTERM   終止程式     軟體終止訊號

SIGKILL   終止程式     殺死程式

SIGALRM 鬧鐘訊號

程式結束訊號 SIGTERM和SIGKILL的區別

SIGTERM比較友好,程式能捕捉這個訊號,根據您的需要來關閉程式。在關閉程式之前,您可以結束開啟的記錄檔案和完成正在做的任務。在某些情況下,假如程式正在進行作業而且不能中斷,那麼程式可以忽略這個SIGTERM訊號。

對於SIGKILL訊號,程式是不能忽略的。這是一個 “我不管您在做什麼,立刻停止”的訊號。假如您傳送SIGKILL訊號給程式,Linux就將程式停止在那裡。

傳送訊號一般有兩種原因:

1(被動式)  核心檢測到一個系統事件.例如子程式退出會像父程式傳送SIGCHLD訊號.鍵盤按下control+c會傳送SIGINT訊號

2(主動式)  通過系統呼叫kill來向指定程式傳送訊號

linux作業系統提供的訊號

[100003@oss235 myppt]$ kill -l

 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL

 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE

 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2

13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT

17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP

21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU

25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH

29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN

35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4

39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8

43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12

47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14

51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10

55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6

59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2

63) SIGRTMAX-1  64) SIGRTMAX

Python提供的訊號

作業系統規定了程式收到訊號以後的預設行為

但是,我們可以通過繫結訊號處理函式來修改程式收到訊號以後的行為

有兩個訊號是不可更改的:SIGTOPSIGKILL

繫結訊號處理函式

執行該程式。然後通過另外一個程式來傳送訊號。

傳送訊號

傳送訊號的程式碼如下:

SIGCHLD訊號

然後顯示一個子程式結束後自動向父程式傳送SIGCHLD訊號的例子。

使用訊號需要特別注意的地方:

如果一個程式收到一個SIGUSR1訊號,然後執行訊號繫結函式,第二個SIGUSR2訊號又來了,第一個訊號沒有被處理完畢的話,第二個訊號就會丟棄。

所以,儘量不要在多執行緒中使用訊號。

 例子演示:

接收訊號的程式,你會發現如果有另外一端使用多執行緒向這個程式傳送訊號,會遺漏一些訊號。

多執行緒發訊號端的程式:

需要的可以下載原始碼

內容補充:

Alarms 是一個特殊訊號型別,它可以讓程式要求系統經過一段時間對自己傳送通知。os 標準模組中指出,它可用於避免無限制阻塞 I/O 操作或其它系統呼叫。

像下面例子,原本程式睡眠 10 後才列印出 print ‘After :’, time.ctime(),但是由於 signal.alarm(2),所以 2 秒後就執行了列印。

注意Signal只有主執行緒才能接收訊號,像下面例子,print ‘Done waiting’ 語句列印不出來,如果不呼叫 signal.alarm(2) ,程式將永遠阻塞。

還有一點需要注意的是,雖然 alarms 類訊號可以在任何執行緒中呼叫,但是隻能在主執行緒中接收,像下面例子即使子執行緒 use_alarm 中呼叫  signal.alarm(1) ,但是不起作用 :

相關文章