Python模塊之信號(signal)

在瞭解了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()中的操做,以針對不一樣的信號實現個性化的處理。

定時發出SIGALRM信號

一個有用的函數是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

相關文章
相關標籤/搜索