zoukankan      html  css  js  c++  java
  • python进程间通信--信号Signal

    信号signal 是python进程间通信多种机制中的其中一种机制。可以对操作系统进程的控制,当进程中发生某种原因而中断时,可以异步处理这个异常。

    信号通过注册的方式‘挂’在一个进程中,并且不会阻塞该进程的运行。一个进程一旦接收到其他进程(可能是应用中的其他进程,也可能使操作系统中的进程)发送的信号就会打断原来的程序执行流程来处理这个信号。

    名词理解:

    异步: 程序在执行中利用内核功能帮助完成必要的辅助操作,不影响应用层持续执行

    注意: 这里的同步和异步机制是相对多进程而言的。

    在多个进程中通信的机制中,只有singal是异步执行的,另外python进程间通信的机制还有pipe(管道),queue(队列),value(共享空间)等等。

    signal可以用在什么地方?

    siganl的应用:

    1. 故障定位技术(进程的底层故障,例如进程突然中断和一些可能性较小的故障)

    2. 对进程的流程控制 

    首先说说与信号signal有关的几个函数

    (1)os.kill(pid,sig)

    发送一个信号给某个进程

    参数解析:

    pid 指定发送信号的进程号

    sig  要发送的信号代号(需要通过signal模块获取)

    (2)signal.alarm(sec)  非阻塞函数

    设置时钟信号,在一定时间后给自身发送一个SIGALRM信号

    原理: 时钟的创建是进程交由操作系统内核(kernal)帮助创建的

    时钟和进程之间是异步执行的,当时钟到时,内核会发送信号给进程,进程接收信号进行相应的响应操作。

    注意:如果设置多个时钟,后面的时钟会覆盖前面的时钟,一个进程只有一个挂起的时钟。

    (3)signal.pause()

    阻塞进程,等待一个信号.当接收到信号时就会停止阻塞

    例如:等待signal()函数的发送

    (4)signal.signal(sig,handler)

    这是信号中最关键的一个方法,用于声明一个信号。当进程运行过程中出现故障异常或者需要进程间通信时,由操作系统内核中的进程或者应用中的进程发出处理信号,通知注册了信号的进程进行处理。

    signal.signal(sig,handler)

    参数理解:

    sig 要处理的信号名称

    handler 信号处理方法  

    可选值: SIG_DFL    表示默认方法处理

                   SIG_IGN    表示忽略这个信号(一般为了避免父进程和子进程的互相干扰而使用)

                   handler       自定义回调函数

     

    自定义回调函数handler:

    这个是当用于在进程捕捉到其他进程发送的信号时调用的函数,当此函数返回时,进程继续继续按原来的逻辑顺序执行。此函数在定义时python普通函数的定义没有区别。函数名不一定是handler,但作为作为参数传入signal()方法的参数名一定是与定义handler函数的函数相同。

    def  handler(signum,frame):

        do  something…

     1)sig :接收到的信号编号,signal模块内部定义了一些常用的内核信号,并为它们进行了编号。

    例如:

    windows操作系统下

    SIGNALINT编号为2

    >>>signal.SIGINT

    <Signals.SIGINT: 2>

    SIGBREAK编号为21

    >>>signal.SIGBREAK

    <Signals.SIGBREAK: 21>

    注意:windows操作系统没有SIGUSR1和SIGUSR2这两个型号类型,linux操作系统才有。

    2) frame:信号结构对象(可以通过结构对象查看信号信息,基本不用)

    signal函数实际上是一个异步的回调函数,只要执行了该函数,则进程任意时候接收到相应信号都会处理。 这里的异步就是上文提到的异步机制,是计算机内核程序与本进程间同时运行,互相不干扰的一种机制,对于进程的正常执行有着关键的作用。这种异步机制在任何后端编程语言中都是存在的,只不过实现的方式和细节不一样而已。

    singnal怎么用?

    一般信号signal是在需要检测异常的程序的开头就定义好了,程序顺序向下运行时,一旦捕获到操作系统发出的signal或者其他进程发出的signal,马上就会停止当前的程序运行状态,去处理捕获到的signal。

    案例:
    注册signal
    import signal
    import os
    import time
    
    print("The process's PID is:",os.getpid())
    def handle_signal(signum,frame):
        print('Received and handle:',signum)
    
    #注册信号处理程序
    signal.signal(signal.SIGUSR1,handle_signal)
    signal.signal(signal.SIGUSR2,handle_signal)
    
    print("The process's PID is:",os.getpid())
    
    while True:
        print('Waiting...')
        print(time.ctime())
        time.sleep(2)
    终端分别输入输入:
    >>> os.kill(7094,signal.SIGUSR1)
    >>> os.kill(7094,signal.SIGUSR2)

    结果:

    Waiting...
    Sat Nov 17 12:19:26 2018
    Waiting...
    Sat Nov 17 12:19:28 2018
    Received and handle: 10
    Waiting...
    Sat Nov 17 12:19:30 2018
    
    Waiting...
    Sat Nov 17 12:22:21 2018
    Received and handle: 12
    Waiting...
    Sat Nov 17 12:22:23 2018

    处理interrupt

    import signal
    import os
    import sys
    import time
    
    print("The process's PID is:",os.getpid())
    
    def handle_signal(signum,frame):
        print('Received and handle:',signum)
    
    def handle_interrupt(signum,frame):
        print('Receive keyboard interrupt')
        sys.exit(0)  #退出进程
    
    #注册信号处理程序
    signal.signal(signal.SIGINT,handle_interrupt)
    signal.signal(signal.SIGUSR1,handle_signal)
    
    while True:
        print('Waiting...')
        print(time.ctime())
        time.sleep(2)

    终端输入:

    >>> os.kill(7625,signal.SIGINT)

    会退出进程

    如果注册函数改为

    signal.signal(signal.SIGINT,signal.SIG_IGN)

    则会忽略终端发出的SIGINT

    时钟

    给signal设定时钟
    def handle_signal(signum,frame):
        print('Time is up!',signum)
        sys.exit()
    
    signal.signal(signal.SIGALRM,handle_signal)
    signal.alarm(3)
    
    while True:
        print(time.ctime())
        time.sleep(1)

    结果:

    Sat Nov 17 13:21:51 2018
    Sat Nov 17 13:21:52 2018
    Sat Nov 17 13:21:53 2018
    Time is up! 14

    附录:

    windows下的sig信号类型

    >>> dir(signal)

    ['CTRL_BREAK_EVENT', 'CTRL_C_EVENT', 'Handlers', 'NSIG', 'SIGABRT', 'SIGBREAK', 'SIGFPE', 'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_IGN', 'Signals', '_IntEnum', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_enum_to_int', '_int_to_enum', '_signal', 'default_int_handler', 'getsignal', 'set_wakeup_fd', 'signal']

    linux下的sig信号类型

    >>> dir(signal)

    ['ITIMER_PROF', 'ITIMER_REAL', 'ITIMER_VIRTUAL', 'ItimerError', 'NSIG', 'SIGABRT', 'SIGALRM', 'SIGBUS', 'SIGCHLD', 'SIGCLD', 'SIGCONT', 'SIGFPE', 'SIGHUP', 'SIGILL', 'SIGINT', 'SIGIO', 'SIGIOT', 'SIGKILL', 'SIGPIPE', 'SIGPOLL', 'SIGPROF', 'SIGPWR', 'SIGQUIT', 'SIGRTMAX', 'SIGRTMIN', 'SIGSEGV', 'SIGSTOP', 'SIGSYS', 'SIGTERM', 'SIGTRAP', 'SIGTSTP', 'SIGTTIN', 'SIGTTOU', 'SIGURG', 'SIGUSR1', 'SIGUSR2', 'SIGVTALRM', 'SIGWINCH', 'SIGXCPU', 'SIGXFSZ', 'SIG_DFL', 'SIG_IGN', '__doc__', '__name__', '__package__', 'alarm', 'default_int_handler', 'getitimer', 'getsignal', 'pause', 'set_wakeup_fd', 'setitimer', 'siginterrupt', 'signal']

    常用信号类型解析

    SIGHUP   断开连接

    SIGINT    ctrl-C

    SIGUIT    ctrl-

    SIGTSTP   ctrl-z

    SIGKILL    终止进程且不能被处理

    SIGSTOP   暂停进程且不能被处理

    SIGALRM   时钟进程

    SIGCHLD   子进程状态改变发送给父进程信息号(但一般父进程不会处理)

    参考文章:

    https://www.cnblogs.com/xautxuqiang/p/5339602.html

    https://www.cnblogs.com/madsnotes/articles/5688681.html


     

  • 相关阅读:
    文章块引用模版
    悬停工具提示
    各个知识点
    Github Fork 缎带.html
    css重置样式
    暗灰色的圆形按钮.html
    css中的居中的方法
    display:table的几个用法 块级子元素垂直居中
    <meta>标签中http-equiv属性的属性值X-UA-Compatible详解
    jQuery难学是因为什么?
  • 原文地址:https://www.cnblogs.com/thomson-fred/p/9502497.html
Copyright © 2011-2022 走看看