3.1 信号其它概念
- 实际执行信号的处理动作称为信号递达(Delivery)
- 信号从产生到递达之间的状态,称为信号未决(Pending)。
- 进程可以选择阻塞 (Block )某个信号(屏蔽)。
被阻塞的信号将保持在未决状态(保存)
,直到进程解除对此信号的阻塞,才执行递达的动作。 - 注意:阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
那上述概念在OS中是如何实现的呢?
每个进程在PCB中都维护了三张表:block、pending、handler。
该三张表就可完成信号的识别、保存和处理工作;handler表中的初始内容,就是程序员内置的特性(信号处理方式)。
因此,关于信号的所有操作,都是围绕这三张表开展的,要横着看这三张表。
3.2 信号操作函数
- 操作sigset_t 类型的数据
- 注意,在使用sigset_ t类型的变量之前,一定要调用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号了。
- 这四个函数都是成功返回0,出错返回-1。sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种信号,若包含则返回1,不包含则返回0,出错返回-1。
sigset_t类型的定义如下:
未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集。 阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),
- 设置进程的block表
sigprocmask
:读取或更改进程的信号屏蔽字(阻塞信号集)。
对于参数how,有以下三个选项:
- 如果oldset是非空指针,则读取进程的当前信号屏蔽字通过oldset参数传出。
- 如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。
- 如果oldset和set都是非空指针,则先将原来的信号屏蔽字备份到oldset里,然后根据set和how参数更改信号屏蔽字。
- 获取当前进程的pending信号集
sigpending
:读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。
下面我们做一个简单的例子来验证上面的函数:
- 先将2号信号屏蔽
- 打印pending信号集
- 发送2号信号,但信号不递达
你是否有这样的疑问: 为什么只给我提供了操作block信号集的方法,没有提供pending与handler表的方法呢?
在信号的产生那里,操作的全是pending表;signal(signum,handler)函数操作的handler表。