信号其他相关常见概念
- 实际执行信号的处理动作称为信号递达(Delivery)
- 信号从产生到递达之间的状态,称为信号未决(Pending)
- 进程可以选择阻塞 (Block )某个信号
- 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作
- 注意:阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作
????在内核中的表示
在Linux内核中,信号的保存主要依赖于三种数据结构:pending表、block表和handler表
pending表:
- pending表是一张位图(bitmap),用于记录当前进程是否收到了信号,以及收到了哪些信号
- 当进程接收到一个信号时,对应的信号位图上的比特位就会由0置1,表示该信号处于未决(Pending)状态
block表:
- block表也是一张位图,用于记录特定信号是否被屏蔽(阻塞)
- 比特位的内容为0表示不屏蔽,为1表示屏蔽。屏蔽的信号在解除屏蔽之前不会被操作系统处理
handler表:
- handler表是一个函数指针数组,用于保存每个信号对应的处理方法
- 这些处理方法可以是默认的,或者忽略的,当然也可以是用户自定义的。当信号被递达时,操作系统会根据handler表找到对应的处理方法并执行
举个例子:上图SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞
????sigset_t
sigset_t是一个在Unix和Linux系统中用于表示信号集的数据类型。信号集本质上是一个信号的集合,用于指定多个信号,通过使用sigset_t,可以轻松地指定一组信号,并在诸如信号阻塞、信号等待等操作中使用这组信号
sigset_t信号集操作函数:
sigemptyset()
:初始化信号集,将其设置为空集sigfillset()
:初始化信号集,将其设置为包含所有信号的集合sigaddset()
:向信号集中添加一个信号sigdelset()
:从信号集中删除一个信号sigismember()
:检查一个信号是否属于某个信号集