信号捕获trap及其实例应用
1、Linux支持的信号(标红部分为常用信号)
信号(Signal):信号是在软件层次上对中断机制的一种模拟,通过给一个进程发送信号,执行相应的处理函数。进程可以忽略信号、捕捉信号和执行缺省操作。其中SIGKILL及SIGSTOP两个信号不能忽略。
1.1、Linux支持的信号列表
编号 | 信号名称 | 缺省动作 | 描述 |
1 | SIGHUP | 终止 | 终止进程,挂起 |
2 | SIGINT | 终止 | 键盘输入中断命令,一般是CTRL+C |
3 | SIGQUIT | CoreDump | 键盘输入退出命令,一般是CTRL+\ |
4 | SIGILL | CoreDump | 非法指令 |
5 | SIGTRAP | CoreDump | trap指令发出,一般调试用 |
6 | SIGABRT | CoreDump | abort(3)发出的终止信号 |
7 | SIGBUS | CoreDump | 非法地址 |
8 | SIGFPE | CoreDump | 浮点数异常 |
9 | SIGKILL | 终止 | 立即停止进程,不能捕获,不能忽略 |
10 | SIGUSR1 | 终止 | 用户自定义信号1,像Nginx就支持USR1信号,用于重载配置,重新打开日志 |
11 | SIGSEGV | CoreDump | 无效内存引用 |
12 | SIGUSR2 | 终止 | 用户自定义信号2 |
13 | SIGPIPE | 终止 | 管道不能访问 |
14 | SIGALRM | 终止 | 时钟信号,alrm(2)发出的终止信号 |
15 | SIGTERM | 终止 | 终止信号,进程会先关闭正在运行的任务或打开的文件再终止,有时间进程在有运行的任务而忽略此信号。不能捕捉 |
16 | SIGSTKFLT | 终止 | 处理器栈错误 |
17 | SIGCHLD | 可忽略 | 子进程结束时,父进程收到的信号 |
18 | SIGCONT | 可忽略 | 让终止的进程继续执行 |
19 | SIGSTOP | 停止 | 停止进程,不能忽略,不能捕获 |
20 | SIGSTP | 停止 | 停止进程,一般是CTRL+Z |
21 | SIGTTIN | 停止 | 后台进程从终端读数据 |
22 | SIGTTOU | 停止 | 后台进程从终端写数据 |
23 | SIGURG | 可忽略 | 紧急数组是否到达socket |
24 | SIGXCPU | CoreDump | 超出CPU占用资源限制 |
25 | SIGXFSZ | CoreDump | 超出文件大小资源限制 |
26 | SIGVTALRM | 终止 | 虚拟时钟信号,类似于SIGALRM,但计算的是进程占用的时间 |
27 | SIGPROF | 终止 | 类似与SIGALRM,但计算的是进程占用CPU的时间 |
28 | SIGWINCH | 可忽略 | 窗口大小改变发出的信号 |
29 | SIGIO | 终止 | 文件描述符准备就绪,可以输入/输出操作了 |
30 | SIGPWR | 终止 | 电源失败 |
31 | SIGSYS | CoreDump | 非法系统调用 |
注意:9 信号,捕获不住,也无法忽略。
1.2、Linux支持的两种信号类型
1、标准信号,编号1-31,称为非可靠信号(非实时),不支持队列,信号可能会丢失,比如发送多次相同的信号,进程只能收到一次,如果第一个信号没有处理完,第二个信号将会丢弃。
2、扩展信号,编号32-64,称为可靠信号(实时),支持队列,发多少次进程就可以收到多少次。
1.3、发送信号的两种情况
第一种是内核检测到系统事件,比如键盘输入CTRL+C会发送SIGINT信号。另一种是通过系统调用kill命令来向一个进程发送信号。
2、trap命令语法格式
语法 | 含义 |
trap ' 触发指令' 信号 | 自定义进程收到系统发出的指定信号后,将执行触发指令,而不会执行原操作 |
trap '' 信号 | 忽略信号的操作 |
trap '-' 信号 | 恢复原信号的操作 |
trap -p | 列出自定义信号操作 |
信号可以3种表达方法:信号的数字2、全名SIGINT、缩写INT
3、trap实例应用
例1:打印0-9,ctrl+c不能终止
#!/bin/bash
trap 'echo press ctrl+c' 2
for ((i=0;i<10;i++));do
sleep 1
echo $i
done
分析:i=0,当i<10,每休眠1秒,i+1,捕获2信号(也就是键盘ctrl+c),并把echo后面的内容输入到终端屏幕。
例2:打印0-5,ctrl+c不能终止,5之后恢复,能终止
#!/bin/bash
trap '' 2
trap -p
for ((i=0;i<5;i++));do
sleep 1
echo $i
done
trap '-' SIGINT
for ((i=5;i<20;i++));do
sleep 1
echo $i
done
分析:i=0,当i<5,每休眠1秒,i+1,捕获2信号;i>5时,解除捕获2信号。