信号概述
在学习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*