1. 程式人生 > >Python模塊之信號學習(signal)

Python模塊之信號學習(signal)

系統調用 情況 tin fin 定時 core 寫到 default 操作系統

信號概述

在學習Python前應該學習下Linux下的信號,軟中斷信號(signal,又簡稱為信號)用來通知進程發生了異步事件。進程之間可以互相通過系統調用kill發送軟中斷信號。內核也可以因為內部事件而給進程發送信號,通知進程發生了某個事件。註意,信號只是用來通知某進程發生了什麽事件,並不給該進程傳遞任何數據。

信號種類

Linux中的信號種類(從圖中可以看到沒有32、33這倆個信號)

普通信號:1-----31號信號

實時信號:34---64號信號

通過指令 kill 信號序號 進程號 可以向一個進程發送信號

技術分享

Python中的信號種類

技術分享

信號的作用

信號的作用在於為倆個不同的進程之間提供交流,我們可以將計算機看作一個大樓,內核(kernel)是大樓的管理員,進程是大樓的房客。每個進程擁有一個獨立的房間(屬於進程的內存空間),而每個房間都是不允許該進程之外的人進入。這樣,每個進程都只專註於自己幹的事情,而不考慮其他進程,同時也不讓別的進程看到自己的房間內部。這對於每個進程來說是一種保護機制,在一些情況,我們需要打破封閉的房間,以便和進程交流信息。我們想讓多個進程之間合作。這樣,我們就需要一定的通信方式。信號(signal)就是一種向進程傳遞信息的方式

信號處理

1) 無視(ignore)信號,信號被清除,進程本身不采取任何特殊的操作

2) 默認(default)操作。每個信號對應有一定的默認操作。比如上面SIGCONT用於繼續進程。

3) 自定義操作。也叫做獲取 (catch) 信號。執行進程中預設的對應於該信號的操作。

進程會采取哪種操作,要根據該進程的程序設計。特別是獲取信號的情況,程序往往會設置一些比較長而復雜的操作(通常將這些操作放到一個函數中)

Python模塊之信號

  在了解了Linux的信號基礎之 後,Python標準庫中的signal包就很容易學習和理解。signal包負責在Python程序內部處理信號,典型的操作包括預設信號處理函數,暫 停並等待信號,以及定時發出SIGALRM等。要註意,signal包主要是針對UNIX平臺(比如Linux, MAC OS),而Windows內核中由於對信號機制的支持不充分,所以在Windows上的Python不能發揮信號系統的功能。

  信號(signal)-- 進程之間通訊的方式,是一種軟件中斷。一個進程一旦接收到信號就會打斷原來的程序執行流程來處理信號。

預設信號處理函數

signal包的核心是使用signal.signal()函數來預設(register)信號處理函數,如下所示:

singnal.signal(signalnum, handler)

signalnum為某個信號,handler為該信號的處理函數。我們在信號基礎裏提到,進程可以無視信號,可以采取默認操作,還可以自定義操作。當handler為signal.SIG_IGN時,信號被無視(ignore)。當handler為singal.SIG_DFL,進程采取默認操作(default)。當handler為一個函數名時,進程采取函數中定義的操作。

信號說明

技術分享
信號名稱    信號說明                                            默認處理
SIGABRT  由程序調用 abort時產生該信號。       程序異常結束。 進程終止並且產生core文件
SIGALRM  timer到期,                                         有alarm或者setitimer 進程終止
SIGBUS    總線錯誤,地址沒對齊等。取決於具體硬件。 結束終止並產生core文件
SIGCHLD  進程停止或者終止時,父進程會收到該信號。 忽略該信號
SIGCONT  讓停止的進程繼續執行                        繼續執行或者忽略
SIGFPE   算術運算異常,除0等。                       進程終止並且產生core文件。
SIGHUP   終端關閉時產生這個信號                    進程終止
SIGILL    代碼中有非法指令                             進程終止並產生core文件
SIGINT    終端輸入了中斷字符ctrl+c              進程終止
SIGIO 異步I/O,跟SIGPOLL一樣。 進程終止
SIGIOT 執行I/O時產生硬件錯誤 進程終止並且產生core文件
SIGKILL 這個信號用戶不能去捕捉它。 進程終止
SIGPIPE 往管道寫時,讀者已經不在了,或者往一個已斷開數據流socket寫數據。 進程終止
SIGPOLL 異步I/O,跟SIGIO一樣。 進程終止
SIGPROF 有setitimer設置的timer到期引發 。 進程終止
SIGPWR Ups電源切換時 進程終止
SIGQUIT Ctrl+\,不同於SIGINT,這個是會產生core dump文件的。 進程終止並且產生core文件
SIGSEGV 內存非法訪問,默認打印出segment fault 進程終止並且產生core文件
SIGSTOP 某個進程停止執行,該信號不能被用戶捕捉。 進程暫停執行
SIGSYS 調用操作系統不認識的系統調用。 進程終止並且產生core文件
SIGTERM 有kill函數調用產生。 進程終止
SIGTRAP 有調試器使用,gdb 進程終止並且產生core文件
SIGTSTP Ctrl+z,掛起進程。 進程暫停
SIGTTIN 後臺程序要從終端讀取成數據時。 進程暫停
SIGTTOU 後臺終端要把數據寫到終端時。 進程暫停
SIGURG 一些緊急的事件,比如從網絡收到帶外數據。 忽略
SIGUSR1 用戶自定義信號 進程終止
SIGUSR2 用戶自定義信號 進程終止
SIGVTALRM 有setitimer產生。 進程終止
信號說明

信號使用實例

1、通過按下CTRL+Z向該進程發送SIGTSTP信號

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‘)

2、利用os.kill(pid, sid)發送信號

import signal
import os
import time

def receive_signal(signum, stack):
    print ‘Received:‘, signum

# 註冊信號處理程序
signal.signal(signal.SIGUSR1, receive_signal)
signal.signal(signal.SIGUSR2, receive_signal)

# 打印這個進程的PID方便使用kill傳遞信號

print ‘My PID is:‘, os.getpid()

# 等待信號,有信號發生時則調用信號處理程序
while True:
    print ‘Waiting...‘
    time.sleep(3)

定時發出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包的核心是設置信號處理函數。除了signal.alarm()向自身發送信號之外,並沒有其他發送信號的功能。但在os包中,有類似於linux的kill命令的函數,分別為

os.kill(pid, sid)

os.killpg(pgid, sid)

分別向進程和進程組(見Linux進程關系)發送信號。sid為信號所對應的整數或者singal.SIG*

Python模塊之信號學習(signal)