文章目录
一、概述
二、信号详解
1. 信号的概念
信号在我们的生活中随处可见, 如:古代战争中摔杯为号;现代战争中的信号弹;体育比赛中使用的信号枪…他们都有共性:
1) 简单
2)不能携带大量信息
3)满足某个特设条件才发送。
信号是信息的载体,Linux/UNIX 环境下,古老、经典的通信方式, 现下依然是主要的通信手段。Unix早期版本就提供了信号机制,但不可靠,信号可能丢失。Berkeley 和 AT&T都对信号模型做了更改,增加了可靠信号机制,但彼此不兼容。POSIX.1对可靠信号例程进行了标准化。
2. 信号的机制
A 给 B 发送信号,B收到信号之前执行自己的代码,收到信号后,不管执行到程序的什么位置,都要暂停运行,去处理信号,处理完毕再继续执行。与硬件中断类似——异步模式。但信号是软件层面上实现的中断,早期常被称为 软中断。
信号的特质:由于信号是通过软件方法实现,其实现手段导致信号有很强的延时性。但对于用户来说,这个延迟时间非常短,不易察觉。
每个进程收到的所有信号,都是由 内核 负责发送的,内核 处理。
3. 与信号相关的事件和状态
(1)产生信号
1)按键产生,如:Ctrl+c、Ctrl+z、Ctrl+
2)系统调用产生,如:kill、raise、abort
3)软件条件产生,如:定时器alarm
4)硬件异常产生,如:非法访问内存(段错误)、除0(浮点数例外)、内存对齐出错(总线错误)
5)命令产生,如:kill命令
- 递达:递送并且到达进程。
- 未决:产生和递达之间的状态。主要由于阻塞(屏蔽)导致该状态。
如下图所示,当 ctl+c 2号信号到达,如果设置为阻塞,且阻塞信号集和未决信号集中状态都为 1,只有当解阻塞该信号时,该信号才会被处理,同时设置未决信号集该信号状态为0。
4. 信号的处理方式
1)执行默认动作
2)忽略(丢弃)
3)捕捉(调用户处理函数)
Linux内核的进程控制块PCB是一个结构体,task_struct,除了包含进程id,状态,工作目录,用户id,组id,文件描述符表,还包含了信号相关的信息,主要指阻塞信号集和未决信号集。
- 阻塞信号集(信号屏蔽字):
将某些信号加入集合,对他们设置屏蔽,当屏蔽x信号后,再收到该信号,该信号的处理将推后(解除屏蔽后)。
- 未决信号集:
1)信号产生,未决信号集中描述该信号的位立刻翻转为1,表示信号处于未决状态。当信号被处理对应位翻转回为0(这一时刻往往非常短暂)。
2)信号产生后,由于某些原因(主要是阻塞)不能抵达。这类信号的集合称之为未决信号集。在屏蔽解除前,信号一直处于未决状态。
5. 信号的编号
可以使用kill –l命令查看当前系统可使用的信号有哪些。
不存在编号为0的信号。其中1-31号信号称之为 常规信号(也叫普通信号或标准信号),34-64称之为 实时信号,驱动编程与硬件相关。名字上区别不大,而前32个名字各不相同。
6. 信号4要素
与变量三要素类似的,每个信号也有其必备4要素,分别是:
1)编号
2)名称
3)事件
4)默认处理动作
可通过man 7 signal查看帮助文档获取:
在标准信号中,有一些信号是有三个“Value”,第一个值通常对alpha和sparc架构有效,中间值针对x86、arm和其他架构,最后一个应用于mips架构,一个‘-’表示在对应架构上尚未定义该信号。
不同的操作系统定义了不同的系统信号。因此有些信号出现在Unix系统内,也出现在Linux中,而有的信号出现在FreeBSD或Mac OS中却没有出现在Linux下。这里我们只研究Linux系统中的信号。重点关注中间的!
默认动作:
- Term:终止进程
- Ign: 忽略信号 (默认即