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()时的异常错误。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值