python进程间通讯--信号Signal

信号signal 是python进程间通讯多种机制中的其中一种机制。能够对操做系统进程的控制,当进程中发生某种缘由而中断时,能够异步处理这个异常。html

信号经过注册的方式‘挂’在一个进程中,而且不会阻塞该进程的运行。一个进程一旦接收到其余进程(多是应用中的其余进程,也可能使操做系统中的进程)发送的信号就会打断原来的程序执行流程来处理这个信号。python

 

名词理解:linux

异步: 程序在执行中利用内核功能帮助完成必要的辅助操做,不影响应用层持续执行编程

注意: 这里的同步和异步机制是相对多进程而言的。windows

 

在多个进程中通讯的机制中,只有singal是异步执行的,另外python进程间通讯的机制还有pipe(管道),queue(队列),value(共享空间)等等。后端

 

signal能够用在什么地方?异步

siganl的应用: 编程语言

1. 故障定位技术(进程的底层故障,例如进程忽然中断和一些可能性较小的故障)函数

2. 对进程的流程控制  ui

 

首先说说与信号signal有关的几个函数

(1)os.kill(pid,sig)

发送一个信号给某个进程

参数解析:

pid 指定发送信号的进程号

sig  要发送的信号代号(须要经过signal模块获取)

 

(2)signal.alarm(sec)  非阻塞函数

设置时钟信号,在必定时间后给自身发送一个SIGALRM信号

 

原理: 时钟的建立是进程交由操做系统内核(kernal)帮助建立的

时钟和进程之间是异步执行的,当时钟到时,内核会发送信号给进程,进程接收信号进行相应的响应操做。

注意:若是设置多个时钟,后面的时钟会覆盖前面的时钟,一个进程只有一个挂起的时钟。

 

(3)signal.pause()

阻塞进程,等待一个信号.当接收到信号时就会中止阻塞

例如:等待signal()函数的发送

 

(4)signal.signal(sig,handler)

这是信号中最关键的一个方法,用于声明一个信号。当进程运行过程当中出现故障异常或者须要进程间通讯时,由操做系统内核中的进程或者应用中的进程发出处理信号,通知注册了信号的进程进行处理。

signal.signal(sig,handler)

参数理解:

sig 要处理的信号名称

handler 信号处理方法  

可选值: SIG_DFL    表示默认方法处理

               SIG_IGN    表示忽略这个信号(通常为了不父进程和子进程的互相干扰而使用)

               handler       自定义回调函数

 

自定义回调函数handler:

这个是当用于在进程捕捉到其余进程发送的信号时调用的函数,当此函数返回时,进程继续继续按原来的逻辑顺序执行。此函数在定义时python普通函数的定义没有区别。函数名不必定是handler,但做为做为参数传入signal()方法的参数名必定是与定义handler函数的函数相同。

def  handler(signum,frame):

    do  something…

 1)sig :接收到的信号编号,signal模块内部定义了一些经常使用的内核信号,并为它们进行了编号。

例如:

windows操做系统下

SIGNALINT编号为2

>>>signal.SIGINT

<Signals.SIGINT: 2>

SIGBREAK编号为21

>>>signal.SIGBREAK

<Signals.SIGBREAK: 21>

注意:windows操做系统没有SIGUSR1和SIGUSR2这两个型号类型,linux操做系统才有。

 

2) frame:信号结构对象(能够经过结构对象查看信号信息,基本不用)

 

signal函数其实是一个异步的回调函数,只要执行了该函数,则进程任意时候接收到相应信号都会处理。 这里的异步就是上文提到的异步机制,是计算机内核程序与本进程间同时运行,互相不干扰的一种机制,对于进程的正常执行有着关键的做用。这种异步机制在任何后端编程语言中都是存在的,只不过实现的方式和细节不同而已。

 

singnal怎么用?

通常信号signal是在须要检测异常的程序的开头就定义好了,程序顺序向下运行时,一旦捕获到操做系统发出的signal或者其余进程发出的signal,立刻就会中止当前的程序运行状态,去处理捕获到的signal。

案例:
注册signal import signal import os import time print("The process's PID is:",os.getpid()) def handle_signal(signum,frame): print('Received and handle:',signum) #注册信号处理程序
signal.signal(signal.SIGUSR1,handle_signal) signal.signal(signal.SIGUSR2,handle_signal) print("The process's PID is:",os.getpid()) while True: print('Waiting...') print(time.ctime()) time.sleep(2)

 

终端分别输入输入:
>>> os.kill(7094,signal.SIGUSR1) >>> os.kill(7094,signal.SIGUSR2)

结果:

Waiting... Sat Nov 17 12:19:26 2018 Waiting... Sat Nov 17 12:19:28 2018 Received and handle: 10 Waiting... Sat Nov 17 12:19:30 2018 Waiting... Sat Nov 17 12:22:21 2018 Received and handle: 12 Waiting... Sat Nov 17 12:22:23 2018

 

 

处理interrupt

import signal import os import sys import time print("The process's PID is:",os.getpid()) def handle_signal(signum,frame): print('Received and handle:',signum) def handle_interrupt(signum,frame): print('Receive keyboard interrupt') sys.exit(0) #退出进程

#注册信号处理程序
signal.signal(signal.SIGINT,handle_interrupt) signal.signal(signal.SIGUSR1,handle_signal) while True: print('Waiting...') print(time.ctime()) time.sleep(2)

终端输入:

>>> os.kill(7625,signal.SIGINT)

会退出进程

 

若是注册函数改成

signal.signal(signal.SIGINT,signal.SIG_IGN)

则会忽略终端发出的SIGINT

 

时钟

给signal设定时钟 def handle_signal(signum,frame): print('Time is up!',signum) sys.exit() signal.signal(signal.SIGALRM,handle_signal) signal.alarm(3) while True: print(time.ctime()) time.sleep(1)

结果:

Sat Nov 17 13:21:51 2018 Sat Nov 17 13:21:52 2018 Sat Nov 17 13:21:53 2018 Time is up! 14

 

附录:

windows下的sig信号类型

>>> dir(signal)

['CTRL_BREAK_EVENT', 'CTRL_C_EVENT', 'Handlers', 'NSIG', 'SIGABRT', 'SIGBREAK', 'SIGFPE', 'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_IGN', 'Signals', '_IntEnum', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_enum_to_int', '_int_to_enum', '_signal', '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']

 

经常使用信号类型解析

SIGHUP   断开链接

SIGINT    ctrl-C

SIGUIT    ctrl-\

SIGTSTP   ctrl-z

SIGKILL    终止进程且不能被处理

SIGSTOP   暂停进程且不能被处理

SIGALRM   时钟进程

SIGCHLD   子进程状态改变发送给父进程信息号(但通常父进程不会处理)

 

参考文章:

https://www.cnblogs.com/xautxuqiang/p/5339602.html

https://www.cnblogs.com/madsnotes/articles/5688681.html

相关文章
相关标签/搜索