• 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

  • 相关阅读:
    BubbleGum96 开箱杂谈与软件资源
    Intel Edision —— 从SSH无法连接到systemd
    Intel Edision —— 开发环境选择一贴通
    Intel Edision —— 上电、基本设置与系统初探
    使用RPi-Monitor监控、统计Guitar的运行状态
    吃我一记咸鱼突刺——使用板载RTC定时开机
    Intel Edison —— 控制GPIO接口,网页显示传感器数值
    docker on UP Board
    Android源码分析--CircleImageView 源码详解
    如何自定义一个优雅的ContentProvider
  • 原文地址:https://www.cnblogs.com/tjp40922/p/15991904.html
Copyright © 2020-2023  润新知