基於python學習筆記——多進程間通訊——Linux信號基礎的學習基礎,進一步學習Python標準庫中的signal模塊。html
儘管signal是python中的模塊,可是主要針對UNIX平臺(好比Linux,MAC OS),而Windows內核中因爲對信號機制的支持不充分,因此在Windows上的Python不能發揮信號系統的功能。python
signal模塊負責python程序內部的信號處理;典型的操做包括信號處理函數、暫停並等待信號,以及定時發出SIGALRM等;segmentfault
引入模塊: import signal 函數
signal.SIGHUP # 鏈接掛斷; signal.SIGILL # 非法指令; signal.SIGINT # 終止進程(ctrl+c); signal.SIGTSTP # 暫停進程(ctrl+z); signal.SIGKILL # 殺死進程(此信號不能被捕獲或忽略); signal.SIGQUIT # 終端退出; signal.SIGTERM # 終止信號,軟件終止信號; signal.SIGALRM # 鬧鐘信號,由signal.alarm()發起; signal.SIGCONT # 繼續執行暫停進程;
設置發送SIGALRM信號的定時器
signal.alarm(time) post
參數:time爲時間參數學習
功能:在time時間後,向進程自身發送SIGALRM信號url
import signal import time signal.alarm(4)#4s後終止程序 while True: time.sleep(1) print("學習python中...")
運行spa
學習python中...
學習python中...
學習python中...
鬧鐘
當在一個程序中出現兩個signal.alarm()函數時操作系統
import signal import time print(signal.alarm(3)) # 0 time.sleep(1) print(signal.alarm(4)) # 2 while True: time.sleep(1) print("學習python中...")
運行.net
0 2 學習python中... 學習python中... 學習python中... 鬧鐘
注意:在一個進程中,只能設置一個時鐘,若是設置第二個則會覆蓋第一個的時間,返回地一個的剩餘時間,第一個鬧鐘返回0。
使用signal.pasue阻塞函數:
signal.pause() Wait until a signal arrives。讓進程進程暫停,以等待信號(什麼信號都可);也即阻塞進程進行,接收到信號後使進程中止
import signal import time print(signal.alarm(3)) # 0 time.sleep(1) print(signal.alarm(4)) # 3 #阻塞等待信號的發生,如論什麼信號均可以 signal.pause() while True: time.sleep(1) print("學習python中...")
運行
0 2 鬧鐘
signal.signal(sig, handler)
功能:按照handler制定的信號處理方案處理函數
參數:
sig:擬需處理的信號,處理信號只針對這一種信號起做用sig
hander:信號處理方案
在信號基礎裏提到,進程能夠無視信號、可採起默認操做、還可自定義操做;當handler爲下列函數時,將有以下操做:
SIG_IGN:信號被無視(ignore)或忽略
SIG_DFL:進程採用默認(default)行爲處理
function:handler爲一個函數名時,進程採用自定義函數處理
*SIGSTOP SIGKILL不能處理,只能採用
示例1
import signal #6s後終止程序 signal.alarm(6) #遇到SIGINT ctrl+c時,忽略SIG_IGN signal.signal(signal.SIGINT,signal.SIG_IGN) signal.pause()
運行後6s 打印出: 鬧鐘
若是在運行中在鍵盤中輸入CTRL+C也無濟於事,此時輸出結果 ^C^C^C^C^C^C^C^C鬧鐘
緣由分析
(1)signal.signal(signal.SIGINT, signal.SIG_IGN) 表示遇到信號SIGINT CTRL + C,時,忽略SIG_IGN該信號。
因此在程序運行中從鍵盤輸入ctrl+c(在終端上顯示 ^C )時無效。
(2)當signal.alarm(6)計時6秒後,直接在終端上輸出 「鬧鐘」 後退出。
(3)signal.pause()是爲了阻塞進程,等待信號。若是沒有這句話,能夠在程序中更變爲
while True: pass
效果同樣,若是沒有這段代碼,則沒有直接運行結束,終端上沒有任何輸出顯示。注意:這裏的signal.alarm()是在程序運行中,6秒後中止進程。
示例2
進程中默認信號方式處理
import signal #6s後終止程序 signal.alarm(6) signal.signal(signal.SIGALRM,signal.SIG_DFL) signal.pause()
運行後終端顯示 鬧鐘
示例3
有些原操做系統規定了的進程收到信號後的默認行爲,使用signal.signal()能夠經過綁定信號處理函數來修改進程收到信號後的行爲,實現個性化處理。
也即改變原默認行爲,可是SIGTOP和SIGKILL兩個信號的默認行爲是不可更變的。
from signal import * import time def handler(signum,frame): if signum == SIGALRM: print('時間到了') elif signum == SIGINT: print("CTRL + C 無效") alarm(5) signal(SIGINT,handler) signal(SIGALRM,handler) while True: print('Waiting....') time.sleep(2)
運行結果
Waiting.... Waiting.... Waiting.... 時間到了 Waiting.... ^CCTRL + C 無效 Waiting.... ^CCTRL + C 無效 Waiting.... ^\退出 (核心已轉儲)
說明:
(1)signal.signal() 經過綁定函數更變了信號的處理方式
(2)若是沒有改變alarm()信號的處理方式,signal.alarm()在運行5s後會將終止程序並輸出「鬧鐘」字樣
(3)從設備終端鍵盤輸入ctrl+c無效後,此時能夠輸入ctrl+\退出程序
(4)def handler(signum,frame)中frame,第一個參數是用來識別信號(signum),第二個信號是用來得到信號發生時,進程棧的情況(stack frame對象),這兩個參數都是由signal.signal()函數傳遞的。 參考 Frame objects
示例4
import signal # Define signal handler function def myHandler(signum, frame): print('I received: ', signum) # register signal.SIGTSTP's handler signal.signal(signal.SIGTSTP, myHandler) signal.pause() print('End of Signal Demo')
運行(運行後設備終端鍵盤輸入ctrl+z)
^ZI received: 20
End of Signal Demo
說明:
(1)signal.signal()函數來預設信號處理函數;
(2)當程序執行signal.pause()來讓進程暫停(被阻塞)以等待信號,此時,按下ctrl + z 向該進程發送SIGTSTP信號,當信號signal.SIGTSTP信號傳遞給該進程後,進程從被阻塞中恢復,並根據預設,執行SIGTSTP的信號處理函數myHandler()。
(3)myHandler()的兩個參數一個用來識別信號(signum),另外一個用來得到信號發生時,進程棧的情況(stack frame);這兩個參數都是有signal.signal()函數傳遞的。
(4)進程並不必定要使用signal.pause()暫停以等待信號,它也能夠在進行工做中接受信號,好比將上面的signal.pause()改成一個須要長時間工做的循環或死循環。
總結:經常使用信號處理函數:
signal.signal(signalnum, handler) 設置信號處理的函數
signal.alarm(time) 設置發送SIGALRM信號的定時器
os.kill 這個不屬於signal模塊,但其可使用給某一進程發送信號
參考: