本文是訊號機制三篇記錄中的第二篇,介紹python語言中負責訊號處理的signal模組,並會給出一些小demo;第一篇簡單介紹了linux訊號機制,第三篇則給出關於訊號的乙個應用。三篇組成乙個系列,想起拋磚引玉的作用,希望對大家能有所幫助。
該模組提供python中訊號處理的機制,下面是幾個常用的方法
1.signal.signal(signalnum, handler)
註冊signalnum訊號量的處理函式為handler
其中signalnum為待註冊的訊號量,handler為該訊號量的處理器,其是乙個可呼叫物件,該物件必須接受兩個引數,分別是訊號量signum,當前程式執行堆疊frame,這兩個引數python直譯器會自動傳入,因此我們不必顯示傳入。關於如何列印堆疊frame的值,可以參考這篇部落格。
這時你也許有疑問,上篇部落格中不是說程式可以忽略訊號嗎?
那是不是說忽略就是直接在handler的函式體中寫個pass就行呢?其實這麼想沒有錯,因為處理完訊號後,程式會回到接收到訊號的地方繼續執行,但這樣寫就不簡潔了。其實handler除了是可呼叫物件外,還可以是以下兩個常量:
1)當handler為signal.sig_dfl時,表示接收訊號後,程式按系統預設行為執行;
2)當handler為signal.sig_ign時,則表示接收訊號後,程式忽略該訊號,繼續自身執行。
關於該方法有兩個注意點:
1)該方法是有返回值的,其將返回之前原有的訊號處理函式;
2)該方法僅能在主線程中註冊訊號處理器,若在子執行緒中註冊,將引發valueerror異常。
2.signal.getsignal(signalnum)
返回目前程式註冊signalnum訊號量的處理函式
返回值可能是python可呼叫物件,signal.sig_dfl,signal.sig_ign或none。
3.signal.pause()
使程式進入睡眠,直到程式接收到某個訊號量
4.signal.alarm(time)
每隔time秒發出乙個alrm訊號
若註冊了alrm訊號的處理函式,則相關處理器會被呼叫。當time為0時,取消註冊alrm訊號處理函式。
1)如果在命令列中,可以用kill命令向對應程序傳送訊號,或者使用快捷鍵(如「ctrl-c」,python程式會收到sigint訊號),具體可參考上篇部落格。
2)如果在python程式中,則可借助python的os模組:
os.kill(pid, signal):向程序號pid對應程序傳送signal訊號量
而程序號的獲取,則可以借助下面兩個方法:
os.getpid():獲取程式的程序id
os.getppid():獲取程式的父程序id
案例一:註冊sigusr1訊號處理器,並在執行過程向程式傳送sigusr1訊號,調起對應處理器
#!/usr/bin/env python3
# coding=utf-8
import os
import time
import signal
import traceback
def handle_sigusr1(signum, frame):
print('handle sighup!'.format(os.linesep, '*' * 100))
print(os.linesep.join(traceback.format_stack(frame))) # 列印詳細執行資訊
def main():
signal.signal(signal.sigusr1, handle_sigusr1) # 註冊sigusr1訊號的處理器為handle_sigusr1函式
print(signal.getsignal(signal.sigusr1)) # 獲取sigusr1訊號目前的處理器
time.sleep(3) # 或者使用signal.pause()
os.kill(os.getpid(), signal.sigusr1) # 向當前程序傳送sigusr1訊號
time.sleep(3)
print('done')
if __name__ == '__main__':
main()
執行結果:
案例二:在子執行緒中註冊某訊號量的處理器,報錯
#!/usr/bin/env python3
# coding=utf-8
from threading import thread
import signal
def child():
signal.signal(signal.sigusr1, signal.sig_ign) # 註冊sigusr1訊號的處理器為signal.sig_ign,即忽略
print('child thread')
def main():
thread = thread(target=child)
thread.start() # 開啟子執行緒
thread.join()
print('done')
if __name__ == '__main__':
main()
執行結果:
案例三:註冊sigchld訊號處理器,子程序結束執行後觸發sigchld訊號,父程序接收
#!/usr/bin/env python3
# coding=utf-8
import os
import signal
def handle_sigchld(signum, frame):
print('handle child process')
def main():
signal.signal(signal.sigchld, handle_sigchld) # 註冊sigchld訊號的處理器為handle_sigchld函式
pid = os.fork()
if pid == 0:
print('child process') # 子程序結束執行後,會向父程序傳送sigchld訊號
else:
print('main process')
os.wait()
print('done')
if __name__ == '__main__':
main()
執行結果:
案例四:註冊sigalrm訊號處理器,定時傳送sigalrm訊號
#!/usr/bin/env python3
# coding=utf-8
import time
import signal
def handle_sigalrm(signum, frame):
print('alarm !'.format(int(time.time())))
def main():
signal.signal(signal.sigalrm, handle_sigalrm) # 註冊sigalrm訊號的處理器為handle_sigalrm函式
signal.alarm(3) # 設定每3秒傳送一次sigalrm訊號
time.sleep(10) # 某些耗時的操作
signal.alarm(0) # 取消定時傳送sigalrm訊號
print('done')
if __name__ == '__main__':
main()
執行結果:
對於訊號量的用途,大家有興趣可以看這篇部落格。
文中如有不當之處,還望大家包容和指出,感謝~
驅動 訊號機制
一 實驗平台 開發板fs2410,採用三星s3c2410的cpu,linux作業系統。二 實現功能 主程式讓四個led燈形成流水燈,當按下開關k1時,熄滅所有燈,並推出程序。三 實驗原理 阻塞和poll機制都是應用程式進行查詢,應用程式是主動的,而裝置時是被動的。訊號機制可以讓裝置主動向應用程式發訊...
Linux 信 號 機 制
前面介紹了訊號的基本概念,在這一節中,我們將介紹核心如何實現訊號機制。即核心如何向乙個程序傳送訊號 程序如何接收乙個訊號 程序怎樣控制自己對訊號的反應 核心在什麼時機處理和怎樣處理程序收到的訊號。還要介紹一下setjmp和longjmp在訊號中起到的作用。1 核心對訊號的基本處理方法 核心給乙個程序...
linux 訊號機制
本文旨在弄懂linux中的訊號工作原理 kill l 命令可以檢視linux下所有訊號 2.1 使用者在終端按下某些鍵時,終端驅動程式會傳送訊號給前台程序 例如ctrl c產生sigint訊號,ctrl 產生sigquit訊號,ctrl z產生sigtstp訊號 2.2 硬體異常產生訊號,這些條件由...