信号的阻塞
每个信号都有两个标志位分别表示阻塞block和未决pending
,还有一个函数指针表示处理动作。(block与pending是两个位图,)
信号产生时,内核在该进程控制块中设置该信号的未决标志位,当信号抵达时,才消除该信号。
posix.1允许递送系统一次或多次该信号,Linux中,在常规信号递达之前产生多次只记一次,而实时信号产生多次,可依此放在一个队列中。
sigset_t 信号集
(pending 和 block 禁止使用位操作,只能使用系统调用)
每个信号的阻塞和未决标志位只有一个比特位,不论产生了几次信号都只记一次
未决和阻塞标志都可以用sigset_t来存储。
sigset_t 可以表示每个信号的有效和无效态。
在阻塞信号集中:有效无效表示该信号是否被阻塞
在未决信号集中:有效无效表示该信号是否未决
阻塞信号集也叫做当前进程的信号屏蔽字(signal mask)
,这里的屏蔽应该理解为阻塞而不是忽略。
sigset_t 保存pending 叫做pending信号集
信号操作集函数
sigset_t 对每种信号用一个bit位来表示有效或无效的状态,该类型对于bit位的实现依赖于系统实现。
我们只能用系统调用来操作sigset_t变量,而不应对它的内部数据做任何解释,比如用printf 打印sigset_t是没有任何意义的。
#include <singal.h>
int sigemptyset(sigset_t *set)
//初始化set所指向的信号集,使其中所有信号对应的bit位清零,表示该信号集包含任何有效信号
int sigfillset(sigset_t *set)
//初始化set所指向的的信号集,使其中所有信号对应的bit位置位,表示该信号集包含系统所支持的所有信号
int sigaddset(sigset_t *set,int signo)
//将对应信号对应bit位置位
int sigdelset(sigset_t *set,int signo)
//删除对应信号位
int sigismember(const sigset_t *set,int signo)
//为一个bool函数,用于判断一个信号集中的有效信号是否包含某种信号
若包含返回1 不包含返回0 失败返回-1
在使用sigset_t类型的变量之前,一定要调用sigemptyset或sigfillset初始化。
初始化sigset_t变量后,就可以使用sigaddset和sigdelset在该信号中添加或删除对应信号。
sigprocmask
#include <singal.h>
int sigprocmask(int how,const sigset_t *set,sigset_t *oset)
//读取或更改进程的信号屏蔽字
//成功返回0 失败返回-1
oset是非空指针:读取进程的信号屏蔽字,通过oset传出
set是非空指针:更改进程的信号屏蔽字,参数how指示如何更改。
oset和set都是非空指针:先将原来的信号屏蔽字备份到oset,然后再根据set和how参数更改信号屏蔽字。
使用mask代表当前信号屏蔽字
how参数的选项
SIG_BLOCK | set包含了我们希望添加到当前信号屏蔽字的信号 mask=mask |
SIG_UNBLOCK | set包含了我们希望从当前信号屏蔽字中解除阻塞的信号 mask=mask&~set |
SIG_SETMASK | 设置当前信号屏蔽字为set所指向的值 相当于 mask=set |
如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回时至少将其中一个信号递达。
sigpending
#include <singal.h>
sigpending(sigset_t *set)
//读取当前进程的未决信号集,通过set参数传出。
调用成功则返回0,出错则返回-1