一、PCB的信号集
之前我们知道每个进程都有一个对应的进程控制块(PCB)用于维护该进程,同样的,对于信号在PCB中会有两个队列去维护它,一个是未决信号集(PEND SIGNAL SET),一个是阻塞信号集(BLOCK SIGNAL SET),在两个信号集中每一位都对应一个信号。对于未决信号集,其中的初始值都是0,代表没有信号到达(注:用户不能设置未决信号集,但是可以读取该信号集中的值),而阻塞信号集是用户可以设置的,若设置为1,则表示阻塞该信号(即使有信号到达也不会处理该信号,直到用户取消阻塞)其过程描述如下:
(点击放大或下载查看)
那么如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的:常规信号(前32个信号)在递达之前产生多次只计一次,而实时信号(后32个信号)在递达之前产生多次可以依次放在一个队列里。本章不讨论实时信号。从上图来看,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。
阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。
二、阻塞信号集的设定过程
一般的操作流程是先构造sigset_t信号集,通过以下函数操作信号集: sigset_t为信号集,可sizeof(sigset_t)察看其大小为128个字节
以下是对信号集的操作: int sigemptyset(sigset_t *set) 清空某个信号集(全置0) int sigfillset(sigset_t *set) 阻塞所有信号(全置1 ) int sigaddset(sigset_t *set, int signo) 将信号集的signo位值1,即阻塞该信号 int sigdelset(sigset_t *set, int signo) 将信号集的signo位值0,即不阻塞该信号 int sigismember(const sigset_t *set, int signo) 测试signo的信号位为1还是0然后使用以sigprocmask函数注册到系统的阻塞信号集中使其生效:
1、sigprocmask
调用函数sigprocmask可以读取或更改进程的信号屏蔽字。 #include int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
返回值:若成功则为0