在瞭解了Linux的信號基礎之 後,Python標準庫中的signal包就很容易學習和理解。signal包負責在Python程序內部處理信號,典型的操做包括預設信號處理函數,暫 停並等待信號,以及定時發出SIGALRM等。要注意,signal包主要是針對UNIX平臺(好比Linux, MAC OS),而Windows內核中因爲對信號機制的支持不充分,因此在Windows上的Python不能發揮信號系統的功能。html
信號(signal)-- 進程之間通信的方式,是一種軟件中斷。一個進程一旦接收到信號就會打斷原來的程序執行流程來處理信號。python
signal包定義了各個信號名及其對應的整數,好比:linux
import signal print(signal.SIGABRT) print(signal.SIG_DFL)
Python所用的信號名與Linux一致,能夠經過$ man 7 signal 查詢編程
signal包的核心是使用signal.signal()函數來預設(register)信號處理函數,以下所示:windows
singnal.signal(signalnum, handler)app
signalnum爲某個信號,handler爲該信號的處理函數。咱們在信號基礎裏提到,進程能夠無視信號,能夠採起默認操做,還能夠自定義操做。當handler爲signal.SIG_IGN時,信號被無視(ignore)。當handler爲singal.SIG_DFL,進程採起默認操做(default)。當handler爲一個函數名時,進程採起函數中定義的操做。ide
參數 | SIG_IGN | SIG_DFL | handler |
---|---|---|---|
解釋 | 忽略 | 默認處理 | 類型的函數指針 |
實質 | #define SIG_IGN ((sighandler_t)1) | #define SIG_IGN ((sighandler_t)0) | 執行本身寫的代碼 |
# Define signal handler function def myHandler(signum, frame): print('I received: ', signum) # register signal.SIGTSTP's handler signal.signal(signal.SIGTSTP, myHandler) #暫停進程,把當前進程置成就緒態,讓出CPU,直到收到任意一個信號後終止,而且當處理完該信號以後,直接執行pause()函數下面的語句 signal.pause() print('End of Signal Demo') # 有問題待測試
在主程序中,咱們首先使用signal.signal()函數來預設信號處理函數。而後咱們執行signal.pause()來讓該進程暫停以等待信號, 以等待信號。當信號SIGUSR1被傳遞給該進程時,進程從暫停中恢復,並根據預設,執行SIGTSTP的信號處理函數myHandler()。 myHandler的兩個參數一個用來識別信號(signum),另外一個用來得到信號發生時,進程棧的情況(stack frame)。這兩個參數都是由signal.singnal()函數來傳遞的。函數
上面的程序能夠保存在一個文件中(好比test.py)。咱們使用以下方法運行:學習
$python test.py測試
以便讓進程運行。當程序運行到signal.pause()的時候,進程暫停並等待信號。此時,經過按下CTRL+Z向該進程發送SIGTSTP信號。咱們能夠看到,進程執行了myHandle()函數, 隨後返回主程序,繼續執行。(固然,也能夠用$ps查詢process ID, 再使用$kill來發出信號。)
(進程並不必定要使用signal.pause()暫停以等待信號,它也能夠在進行工做中接受信號,好比將上面的signal.pause()改成一個須要長時間工做的循環。)
咱們能夠根據本身的須要更改myHandler()中的操做,以針對不一樣的信號實現個性化的處理。
一個有用的函數是signal.alarm(),它被用於在必定時間以後,向進程自身發送SIGALRM信號:
import signal # Define signal handler function def myHandler(signum, frame): print("Now, it's the time") exit() # register signal.SIGALRM's handler signal.signal(signal.SIGALRM, myHandler) signal.alarm(5) while True: print('not yet')
咱們這裏用了一個無限循環以便讓進程持續運行。在signal.alarm()執行5秒以後,進程將向本身發出SIGALRM信號,隨後,信號處理函數myHandler開始執行。
signal包的核心是設置信號處理函數。除了signal.alarm()向自身發送信號以外,並無其餘發送信號的功能。但在os包中,有相似於linux的kill命令的函數,分別爲
os.kill(pid, sid)
os.killpg(pgid, sid)
分別向進程和進程組(見Linux進程關係)發送信號。sid爲信號所對應的整數或者singal.SIG*。
實際上signal, pause,kill和alarm都是Linux應用編程中常見的C庫函數,在這裏,咱們只不過是用Python語言來實現了一下。實際上,Python 的解釋器是使用C語言來編寫的,因此有此類似性也並不意外。此外,在Python 3.4中,signal包被加強,信號阻塞等功能被加入到該包中。咱們暫時不深刻到該包中。
signal.SIG*
signal.signal()
signal.pause() signal.pause
阻塞函數,讓進程暫停以等待信號,也就時阻塞進程執行,簡單來講當接收到信號後使進程中止。
signal.alarm() 經常使用做定時器,time
爲時間參數,單位爲秒
SIGINT
表示終止進程
SIGQUIT
表示退出進程
SIGSTP
表示暫停進程
SIGKILL
表示結束某個進程,不能被忽略處理。
SIGALRM
表示時鐘信號,經常使用做定時器,time
爲時間參數,單位爲秒。
SIGSTOP
表示中止某個進程,且不能被忽略處理。
SIGCHLD
表示子進程發送給父進程信號
SIGCONT 繼續執行暫停的進程
SIGINT 終止進程 中斷進程,不可經過signal.signal()捕捉(至關於Ctrl+C)
SIGTERM 終止進程 軟件終止信號,可經過signal.signal()捕捉(默認信號,當os.kill()沒有指明信號類型時,默認的是該信號)
SIGKILL 終止進程 殺死進程,不可捕捉(至關於linux下的kill命令,windows下使用會拋出異常)
SIGALRM 鬧鐘信號 能夠經過signal.alarm()和os.kill()發送該信號,可經過signal.signal()捕捉
windows下只能使用這幾個信號:
SIGABRT
SIGFPE
SIGILL
SIGINT
SIGSEGV
SIGTERM