0


Python之signal模块详解

信号:进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。操作系统规定了进程收到信号以后的默认行为,但是,我们可以通过绑定信号处理函数来修改进程收到信号以后的行为,有两个信号是不可更改的SIGTOP和SIGKILL。

发送信号一般有两种原因:
1(被动式) 内核检测到一个系统事件.例如子进程退出会像父进程发送SIGCHLD信号.键盘按下control+c会发送SIGINT信号
2(主动式) 通过系统调用kill来向指定进程发送信号

接收信号的进程对不同的信号有三种处理方法:

  1. 指定处理函数
  2. 忽略
  3. 根据系统默认值处理, 大部分信号的默认处理是终止进程

设置信号处理函数

signal.signal(signum, handler) 

功能:按照handler制定的信号处理方案处理函数

参数

signum:拟需处理的信号,处理信号只针对这一种信号起作用sig

hander:信号处理方案

在信号基础里提到,进程可以无视信号、可采取默认操作、还可自定义操作;当handler为下列函数时,将有如下操作:

SIG_IGN:信号被无视(ignore)或忽略

SIG_DFL:进程采用默认(default)行为处理

自定义函数:handler为一个函数名时,进程采用自定义函数处理

SIGSTOP SIGKILL不能处理,只能采用

关于该方法有两个注意点:

1)该方法是有返回值的,其将返回之前原有的信号处理函数;

2)该方法仅能在主线程中注册信号处理器,若在子线程中注册,将引发ValueError异常。

handle的基本定义格式如下:

def handle(signum,frame):
    pass

其中signum为待注册的信号量,frame为当前程序运行堆栈frame

计时器alarm

在C语言中有个setitimer函数,函数setitimer可以提供三种定时器,它们相互独立,任意一个定时完成都将发送定时信号到进程,并且自动重新计时。参数which确定了定时器的类型:

  1. ITIMER_REAL 定时真实时间,与alarm类型相同。 SIGALRM
  2. ITIMER_VIRT 定时进程在用户态下的实际执行时间。 SIGVTALRM
  3. ITIMER_PROF 定时进程在用户态和核心态下的实际执行时间。 SIGPROF

这三种定时器定时完成时给进程发送的信号各不相同,其中ITIMER_REAL类定时器发送SIGALRM信号,ITIMER_VIRT类定时器发送SIGVTALRM信号,ITIMER_REAL类定时器发送SIGPROF信号。

函数alarm本质上设置的是低精确、非重载的ITIMER_REAL类定时器,它只能精确到秒,并且每次设置只能产生一次定时。函数setitimer设置的定时器则不同,它们不但可以计时到微妙(理论上),还能自动循环定时。在一个Unix进程中,不能同时使用alarm和ITIMER_REAL类定时器

signal.alarm(time)

调用后过time秒发出一个ALRM信号

若注册了SIGALRM信号的处理函数,则相关handle会被调用。当time为0时,取消注册ALRM信号处理函数。

getsignal函数

signal.getsignal(signalnum)

返回目前程序注册signalnum信号量的处理函数

返回值可能是Python函数,signal.SIG_DFL,signal.SIG_IGN或None。

pause函数

signal.alarm(time)

使程序进入睡眠,直到程序接收到某个信号量

setitimer函数

signal.setitimer(which, seconds[, interval])

设置一个时间计时器,在经过seconds时间后触发which(signal.ITIMER_REAL, signal.ITIMER_VIRTUAL or signal.ITIMER_PROF),并且以后每隔interval时间进行轮训。interval设置为0表示清除which。

getitimer函数

signal.getitimer(which)

返回一个当前which指定的interval时间。

set_wakeup_fd函数

signal.set_wakeup_fd(fd)
设置唤醒一个fd,当收到相关信号后

siginterrupt函数

signal.siginterrupt(signalnum, flag)

改变默认的系统调用行为,如果flag设置为False,当收到中断信号后,系统调用会被重新启动。

如何发送信号

1)如果在命令行中,可以用kill命令向对应进程发送信号,或者使用快捷键(如「CTRL-C」,Python程序会收到SIGINT信号),具体可参考上篇博客。

2)如果在Python程序中,则可借助Python的os模块:

os.kill(pid, signal):向进程号pid对应进程发送signal信号量

而进程号的获取,则可以借助下面两个方法:

os.getpid():获取程序的进程ID

os.getppid():获取程序的父进程ID

异常

signal.ItimerError
获取在执行setitimer()和getitimer()时的异常错误。

标签:

本文转载自: https://blog.csdn.net/baidu_39133469/article/details/115416674
版权归原作者 头真的好大哦 所有, 如有侵权,请联系我们删除。

“Python之signal模块详解”的评论:

还没有评论