python之signal操作
1 信号的意义
在linux系统中信号是与进程通信的一种手段。假设没有信号,linux中的进程一旦运行起来将不再受控,这种局面对于进程的管理来说是一种灾难。kill、ctrl+c等操作本质上就是我们向linux发出的信号,进程接收到信号后根据相应的策略做出反馈。
2 信号的来源
A) 通过终端(组合键)产生信号
最典型的ctrl+c终止当前进程
B) 硬件异常产生信号
例如进程运行中内存的寻址出现异常,就会发出信号。
C) 显式的调用linux命令产生信号
最典型的kill命令,通过linux命令发出信号干预进程运行
D) 软件代码发送信号
Java本地方法、Python signal类包等,通过程序发出信号。
3 有哪些信号
执行命令$kill -l可以看到信号列表
可以看到有62种信号,32、33轮空;1-31号为不可靠信号,是linux自带的与进程通信的信号;34-64是可靠信号,是为了弥补linux不可靠信号太少而扩展的。不可靠信号多次发出最终只响应1次;而可靠信号每次都有响应。
执行命令$man 7 signal可以更详细的查看每一种信号的意义:
例如我们前面说过的ctrl+c,对应的是2号sigint;kill对应的是9号sigkill;内存错误对应的11号sigsegv。
4 进程会如何处理这些信号
并不是每种信号进程都要给出反馈的,进程对待信号会有3种策略:
A) 忽略此信号
好理解,就是假装没看见,不鸟它。
B) 执行默认动作
例如终止进程等
C) 提供一个信号处理函数,要求内核执行该函数
通过某种形式在发送信号时同时给定处理信号的函数,相当于回调函数
5 python对信号的支持
Python对信号的操作在importsignal这个包里,有了前面知识的积累,我们很好理解signal包调用的侧重点:哪种信号?如何处理?如何发送?
A) 哪种信号?
Linux的62种信号,signal包已经都搬到python中来了,需要开发人员自己选择一种
B) 如何处理?
Signal默认提供了Ignal和Default2种策略,同时支持开发人员自定义回调函数
C) 如何发送?
Signal对信号的发送做了简易的封装,例如alarm()函数发起sigalrm信号
6 案例,做一个timeout的自定义annotation:
import signal def timeout(seconds=10, error_message="connect to server timeout"): def decorator(func): def _handle_timeout(signum, frame): raise TimeoutError(error_message) def wrapper(*args, **kwargs): signal.signal(signal.SIGALRM, _handle_timeout) signal.alarm(seconds) try: result = func(*args, **kwargs) finally: signal.alarm(0) return result return wraps(func)(wrapper) return decorator
先定制了一个回调函数decorator,超时后直接抛异常;
然后通过signal.signal()方法决定了信号种类和处理方式,第一个参数可以替换成62种信号的其中一种,第二个参数还可以传入SIG_DFL或SIG_IGN;
最后通过signal.alarm()函数发起信号。
这样我就自己开发了一个超时处理机制。
@timeout(1200) def ready_host(**not_connected): while True: if not any(not_connected): break for h in not_connected.keys(): if check_port_is_open(h): del not_connected[h] return True ———————————————— 版权声明:本文为CSDN博主「牛麦康纳」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/yejingtao703/article/details/80659458
原文链接:https://blog.csdn.net/yejingtao703/article/details/80659458