訊號機制 Python訊號處理 signal模組

2021-08-20 03:30:21 字數 4201 閱讀 2542

本文是訊號機制三篇記錄中的第二篇,介紹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 硬體異常產生訊號,這些條件由...