python模塊之signal信號

簡介

做用:發送和接收異步系統信號python

  信號是一個操做系統特性,它提供了一個途徑能夠通知程序發生了一個事件並異步處理這個事件。信號能夠由系統自己生成,也能夠從一個進程發送到另外一個進程。linux

因爲信號會中斷程序的正常控制流,若是在中間接收到信號,有些操做(特別是I/O操做)可能會發生錯誤。windows

接收信號

  signal.signal(sig,action)異步

  sig爲某個信號,action爲該信號的處理函數函數

  例如:ui

    signal.signal(signal.SIGALRM, hanlder)       hanlder爲信號處理函數操作系統

windows下sig信號:blog

>>> dir(signal)
  ['CTRL_BREAK_EVENT', 'CTRL_C_EVENT', 'NSIG', 'SIGABRT', 'SIGBREAK', 'SIGFPE',
   'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_IGN', '__doc__', '__name__', '__package__', 
  'default_int_handler', 'getsignal', 'set_wakeup_fd', 'signal']

linux下sig信號:進程

>>> dir(signal)
  ['ITIMER_PROF', 'ITIMER_REAL', 'ITIMER_VIRTUAL', 'ItimerError', 'NSIG', 'SIGABRT', 'SIGALRM', 'SIGBUS', 'SIGCHLD', 
  'SIGCLD', 'SIGCONT', 'SIGFPE', 'SIGHUP', 'SIGILL', 'SIGINT', 'SIGIO', 'SIGIOT', 'SIGKILL', 'SIGPIPE', 'SIGPOLL', 
  'SIGPROF', 'SIGPWR', 'SIGQUIT', 'SIGRTMAX', 'SIGRTMIN', 'SIGSEGV', 'SIGSTOP', 'SIGSYS', 'SIGTERM', 'SIGTRAP', 
  'SIGTSTP', 'SIGTTIN', 'SIGTTOU', 'SIGURG', 'SIGUSR1', 'SIGUSR2', 'SIGVTALRM', 'SIGWINCH', 'SIGXCPU', 'SIGXFSZ',
   'SIG_DFL', 'SIG_IGN', '__doc__', '__name__', '__package__', 'alarm', 'default_int_handler', 'getitimer', 'getsignal',
   'pause', 'set_wakeup_fd', 'setitimer', 'siginterrupt', 'signal']

即經過創建一個回調函數來接收信號,這個回調函數稱爲信號處理函數(signal hanlder),它會在信號出現時調用。事件

 信號處理函數包括信號編號及被信號中斷那一時刻的棧幀。

  def hanlder(signum, frame):

      something...

  signum即信號編號( 數字),例如:

>>> import signal
>>> signal.SIGINT
  2

  frame爲被信號中斷那一時刻的棧幀。

接收信號

signal.signal(sig,action)

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)

SIGUSR1和SIGUSR2是留給用戶使用的信號。windows下無這兩個信號。

這個腳本會無限循環,每次暫停3秒鐘。有信號到來時,sleep()調用被中斷,信號處理程序receive_signal被調用.信號處理程序返回時,循環繼續。

發送信號

os.kill(pid, sig):pid爲進程號, sig爲信號

>>> import os
>>> help(os.kill)
Help on built-in function kill in module nt:

kill(...)
    kill(pid, sig)
    
    Kill a process with a signal.

>>> 
import os
import signal
import time

def signal_usr1(signum, frame):
    "Callback invoked when a signal is received"
    pid = os.getpid()
    print 'Received USR1 in process %s' % pid

print 'Forking...'
child_pid = os.fork()
if child_pid:
    print 'PARENT: Pausing before sending signal...'
    time.sleep(1)
    print 'PARENT: Signaling %s' % child_pid
    os.kill(child_pid, signal.SIGUSR1)
else:
    print 'CHILD: Setting up a signal handler'
    signal.signal(signal.SIGUSR1, signal_usr1)
    print 'CHILD: Pausing to wait for signal'
    time.sleep(5)

父進程使用kill()和signal模塊向子進程發送信號。在父進程中,使用kill()發送一個USR1信號以前會暫停很短一段時間,這個短暫的暫停使子進程有時間創建信號處理程序。

signal.pause():等待直到接收一個信號

import signal
import os 
import time

def do_exit(sig, stack):
    raise SystemExit('Exiting')

# 將SIGINT的默認處理程序替換爲SIG_IGN
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGUSR1, do_exit)

print 'My PID:', os.getpid()

signal.pause()

正常狀況下,SIGINT會產生一個KeyboardInterrupt,這個例子將忽略SIGINT,並在發現SIGUSR1時產生一個SystemExit。

signal.alarm(time):若是time是非0,這個函數則響應一個SIGALRM信號並在time秒後發送到該進程。

import signal
import time

def received_alarm(signum, stack):
    print 'Alarm:', time.ctime()

# Call receive_alarm in seconds
signal.signal(signal.SIGALRM, received_alarm)
signal.alarm(2)

print 'Before:', time.ctime()
time.sleep(4)
print 'After:', time.ctime()
相關文章
相關標籤/搜索