python处理signal(信号)

(1)signal模块介绍

信号是一种进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号,处理完信号后再继续原来的程序执行流程。

signal包负责在python程序内部处理信号,典型的操作包括预设信号处理函数,暂停并等待信号,以及定时发出SIGALRM等。

windows和Linux都可以使用signal库,但是部分信号只支持Linux,比如signal.SIGALRM。所以使用signal库时要注意平台,详情可以参考文档:signal --- 设置异步事件处理器 --- Python 3.13.3 文档

python自带的处理信号的库是signal。

(2)使用示例

1.预设信号处理函数

python 复制代码
# -*- coding:utf-8 -*-
import signal


def handler(sig, frame):
    # 处理函数handler的形参是固定的
    # sig代表信号值,是一个整数,信号编号
    # frame 参数,是一个栈帧对象,它包含当前调用栈的信息(如局部变量、函数调用链等)
    print(f"sig: {sig}")
    print(f"frame: {frame}")

if __name__ == "__main__":
    signal.signal(signal.SIGTSTP, handler)
    signal.pause()

上述代码含义:当接收到停止终端信号(signal.SIGTSTP),调用处理函数handler,输出信号值和进程栈信息。

由结果可知,接收到的信号值为20,frame值为: <frame at 0xb670fc30, file '1.py', line 12, code <module>>

解释

  • signal.signal(signalnum, handler)函数有两个参数:signalnum: 某个信号,比如signal.SIGTSTP;handler: 信号处理函数。
  • signal调用hander的时候,会传递两个参数:signum: 这个就是信号值,也就是signalnum;frame: 这个参数是用来获得信号发生时,进程栈的情况。

2.定时发出信号

使用的函数是:signal.alarm()

该函数被用于在一定时间之后,向进程自身发送SIGALRM信号。

python 复制代码
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import signal
import time
import datetime

def handler(sig, frame):
    print(datetime.datetime.now())
    print("handler function")

if __name__ == "__main__":
    signal.signal(signal.SIGALRM, handler)
    print(datetime.datetime.now())
    signal.alarm(5)
    time.sleep(10)
    print(datetime.datetime.now())
    print("main function")

上述代码含义:程序运行5秒后向自身发送SIGALRM信号,调用handler函数。主程序运行10秒之后打印信息。为了证明signal.alarm(5)确实生效了,特意添加了一些打印时间的信息。运行结果如下:

由上图输出结果可知:

11:32:37,程序开始运行

11:32:42,handler函数被调用起来了,时间经过了11:32:42 - 11:32:37 = 5秒。说明signal.alarm(5)生效了。

11:32:47,从程序运行,到现在共10秒,接着输出主函数后面的内容。

程序总共耗时10秒钟,由此也可以推断出,signal.alarm()函数不是阻塞式的。

以上程序是在linux上运行的,如果换到windows上运行会报错:

AttributeError: module 'signal' has no attribute 'SIGALRM'

原因前面讲过了,部分信号只支持Linux

(3)常见signal信号

系统中的信号载体都有一个名字,以"SIG"开头,每个信号都有对应的编号。

注意信号是软件中断。

不存在编号为0的信号。

1.Linux系统上有哪些信号

执行命令man 7 signal或者kill -l查看

man 7 signal

kill -l

说明:

  • SIGHUP - 1: 连接断开。
  • SIGINT - 2:中断信号,例如键盘按下:CTRL + C。
  • SIGQUIT - 3:退出信号,例如键盘按下: CTRL + \。可以进去python解释器,按下ctrl+\就会退出Python解释器。
  • SIGILL - 4:非法(硬件)指令
  • SIGTRAP - 5: 指示一个实现定义的硬件故障。执行断点指令时,常用此信号将控制转移至调试程序。(断点调试用?)
  • SIGABRT - 6: 夭折信号,进程调用abort函数时产生这种信号,进程异常终止。
  • SIGBUS - 7: 内存故障,产生此种信号。
  • SIGFPE - 8: 表示一个算术运算异常,如除以0、浮点溢出等。
  • SIGKILL - 9: 终止信号,例如:kill -9 xxpid,用于进程的立即终止,不能被忽略或阻止,进程与其线程一起终止,适用于无响应的进程。暴力~
  • SIGUSR1 - 10: 用户定义的信号,可用于应用程序。
  • SIGSEGV - 11: 硬件异常产生的信号,比如除数为0、无效的内存引用等。
  • SIGUSR2 - 12: 用户定义的信号,可用于应用程序。
  • SIGPIPE - 13: 在管道的读进程已终止后,一个进程写此管道,会产生该信号。店已打烊,请勿来访~
  • SIGALRM - 14: 闹钟信号,由alarm函数设置的定时器超时后产生此信号。
  • SIGTERM - 15: 终止信号。软终止,kill命令默认发送SIGTERM信号。该信号让程序有机会在退出之前做好清理工作,优雅地终止。和kill -9相比,SIGTERM不会杀死子进程。
  • SIGSTKFLT - 16: 仅由Linux定义,它出现在Linux的早期版本,企图用于数据协处理器的栈故障。该信号并非由内核产生,但仍保留以向后兼容。
  • SIGCHLD - 17: 子进程状态改变。当一个进程终止或停止时,SIGCHLD信号被送给其父进程。需要父进程去捕捉,因为SIGCHLD信号默认是忽略的。
  • SIGCOUT - 18: 使暂停进程继续。系统会根据进程状态判定默认动作,如果接收到该信号的进程是停止状态,默认动作是继续;否则默认动作是忽略此信号。
  • SIGSTOP - 19: 停止
  • SIGTSTP - 20: 停止终端输入。例如:键盘按下CTRL + Z。
  • SIGTTIN - 21: 当一个后台进程组进程试图读其控制终端时,终端驱动程序产生此信号。
  • SIGTTOU - 22: 当一个后台进程组进程试图写其控制终端时,终端驱动程序产生此信号。
  • SIGURG - 23: 在网络连接上传来带外的数据。通知进程已经发生了一个紧急情况。
  • SIGXCPU - 24: 超过软CPU时间(疑惑:软CPU时间指的是发生中断CPU做指定请求处理消耗的时间?)限制,则产生此信号。
  • SIGXFSZ - 25: 如果进程超过了其软文件长度限制,则产生此信号。
  • SIGVTALRM - 26: 当一个由setitimer(2)函数设置的虚拟间隔时间已经超时时,产生此信号。
  • SIGPROF - 27: 当setitimer(2)函数设置的梗概统计间隔定时器已经超时时产生此信号。
  • SIGWINCH - 28: 内核维持与每个终端或伪终端相关联窗口的大小。如果ioctl更改了窗口大小,内核会将SIGWINCH信号发送给前台进程组。
  • SIGIO - 29: 此信号指示一个异步I/O事件。
  • SIGPWR - 30: 主要用于不间断电源(UPS)的系统。如果电源失效,则UPS启动,系统如果能依靠蓄电池继续运行,无需做任何处理;如果蓄电池也不能使系统继续运行,此时就会发送SIGPWR信号给init进程,然后由init进程处理停机操作。
  • SIGSYS - 31: 当进程执行了一条机器指令,但是参数却是无效的,会产生该信号。
  • SIGRTMIN - 32: 编号32之后的信号都是自定义信号,还未接触,以后用到了在这补充~

2.常见windows信号

连接挂断

signal.SIGUP

非法指令

signal.SIGILL

终止进程

SIGINT信号编号为2,当按下键盘CTRL+c组合键时进程会收到此信号,用于终止进程。

signal.SIGINT

暂停进程CTRL+z

signal.SIGSTP

杀死进程,此信号不能被捕获或忽略。

SIGKILL信号用于强制杀死进程,此信号进程无法忽视,直接在系统层面将进程杀死,所以在Python中它是不能监听的。

signal.SIGKILL

终端退出

signal.SIGQUIT

终止信号,软件终止信号。

当终端用户输入kill sigerm pid时对应PID的进程会接收到此信号,此信号进程是可以捕获并指定函数处理。比如做一下程序清理等工作,当然也是可以忽视此信号的。

signal.SIGTERM

继续执行暂停进程

signal.SIGCONT


end

相关推荐
黑不拉几的小白兔7 分钟前
第十五届蓝桥杯大赛软件赛国赛Python 大学 C 组试做【本期题单: 设置密码、栈】
c语言·python·蓝桥杯
ZHPEN18 分钟前
python打卡day38
python
病树前头21 分钟前
服务器tty2终端如何关机
linux·运维·服务器
灏瀚星空26 分钟前
Tesseract 字库介绍与训练指南
经验分享·笔记·爬虫·python
m0_5195231033 分钟前
Linux——数据链路层
linux·服务器·网络
love530love40 分钟前
【笔记】解决启动Anaconda Toolbox报错ModuleNotFoundError: No module named ‘pysqlite2‘
开发语言·人工智能·windows·笔记·python·conda
梦醒沉醉41 分钟前
Python教程(七)——错误和异常
python
编程自留地43 分钟前
第12次05: 用户中心-用户基本信息
python·django·商城
知福致福1 小时前
服务器上用脚本跑python深度学习的注意事项(ubantu系统)
运维·服务器·python
坏坏-51 小时前
CentOS 7.0重置root密码
linux·运维·centos