在liunx系统中要想每隔一分钟执行一个呼吁,最普遍的要领就是crontab了,假如不想利用crontab,经同事指点在措施中可以用按时器实现这种成果,于是就开始探索了,发明需要一些信号的常识…
查察你的linux支持哪些信号:kill -l 即可
root@server:~# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX root@server:~#
信号:历程之间通讯的方法,是一种软件间断。一个历程一旦吸收到信号就会打断本来的措施执行流程来处理惩罚信号。操纵系统划定了历程收到信号今后的默认行为,可是,我们可以通过绑定信号处理惩罚函数来修改造程收到信号今后的行为,有两个信号是不行变动的SIGTOP和SIGKILL。
发送信号一般有两种原因:
1(被动式) 内核检测到一个系统事件.譬喻子历程退出会像父历程发送SIGCHLD信号.键盘按下control+c会发送SIGINT信号
2(主动式) 通过系统挪用kill来向指定历程发送信号
在C语言中有个setitimer函数,函数setitimer可以提供三种按时器,它们彼此独立,任意一个按时完成都将发送按时信号到历程,而且自动从头计时。参数which确定了按时器的范例:
ITIMER_REAL 按时真及时间,与alarm范例沟通。 SIGALRM
ITIMER_VIRT 按时历程在用户态下的实际执行时间。 SIGVTALRM
ITIMER_PROF 按时历程在用户态和焦点态下的实际执行时间。 SIGPROF
这三种按时器按时完成时给历程发送的信号各不沟通,个中ITIMER_REAL类按时器发送SIGALRM信号,ITIMER_VIRT类按时器发送SIGVTALRM信号,ITIMER_REAL类按时器发送SIGPROF信号。
函数alarm本质上配置的是低准确、非重载的ITIMER_REAL类按时器,它只能准确到秒,而且每次配置只能发生一次按时。函数setitimer配置的按时器则差异,它们不单可以计时到微妙(理论上),还能自动轮回按时。在一个Unix历程中,不能同时利用alarm和ITIMER_REAL类按时器。
SIGINT 终止历程 间断历程 (control+c)
SIGTERM 终止历程 软件终止信号
SIGKILL 终止历程 杀死历程
SIGALRM 闹钟信号
前期的常识也筹备的差不多了,该向python的signal进军了。
界说信号名
signal包界说了各个信号名及其对应的整数,好比
import signal print signal.SIGALRM print signal.SIGCONT
Python所用的信号名和Linux一致。你可以通过
$man 7 signal
查询
预设信号处理惩罚函数
signal包的焦点是利用signal.signal()函数来预设(register)信号处理惩罚函数,如下所示:
singnal.signal(signalnum, handler)
#p#分页标题#e#
signalnum为某个信号,handler为该信号的处理惩罚函数。我们在信号基本里提到,历程可以无视信号,可以采纳默认操纵,还可以自界说操纵。当handler为signal.SIG_IGN时,信号被无视(ignore)。当handler为singal.SIG_DFL,历程采纳默认操纵(default)。当handler为一个函数名时,历程采纳函数中界说的操纵。
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')
在主措施中,我们首先利用signal.signal()函数来预设信号处理惩罚函数。然后我们执行signal.pause()来让该历程暂停以期待信号,以期待信号。当信号SIGUSR1被通报给该历程时,历程从暂停中规复,并按照预设,执行SIGTSTP的信号处理惩罚函数myHandler()。myHandler的两个参数一个用来识别信号(signum),另一个用来得到信号产生时,历程栈的状况(stack frame)。这两个参数都是由signal.singnal()函数来通报的。
上面的措施可以生存在一个文件中(好比test.py)。我们利用如下要领运行:
$python test.py
以便让历程运行。当措施运行到signal.pause()的时候,历程暂停并期待信号。此时,通过按下CTRL+Z向该历程发送SIGTSTP信号。我们可以看到,历程执行了myHandle()函数, 随后返回主措施,继承执行。(虽然,也可以用$ps查询process ID, 再利用$kill来发出信号。)
(历程并不必然要利用signal.pause()暂停以期待信号,它也可以在举办事情中接管信号,好比将上面的signal.pause()改为一个需要长时间事情的轮回。)
我们可以按照本身的需要变动myHandler()中的操纵,以针对差异的信号实现本性化的处理惩罚。
按时发出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.alarm()执行5秒之后,历程将向本身发出SIGALRM信号,随后,信号处理惩罚函数myHandler开始执行。
发送信号
signal包的焦点是配置信号处理惩罚函数。除了signal.alarm()向自身发送信号之外,并没有其他发送信号的成果。但在os包中,有雷同于linux的kill呼吁的函数,别离为
os.kill(pid, sid) os.killpg(pgid, sid)
别离向历程和历程组(见Linux历程干系)发送信号。sid为信号所对应的整数可能singal.SIG*。
实际上signal, pause,kill和alarm都是Linux应用编程中常见的C库函数,在这里,我们只不外是用Python语言来实现了一下。实际上,Python 的表明器是利用C语言来编写的,所以有此相似性也并不料外。另外,在Python 3.4中,signal包被加强,信号阻塞等成果被插手到该包中。我们临时不深入到该包中。