-
信号阻塞
概念
- 信号递达:执行信号的处理过程叫做信号递达(Delivery)。
- 信号未决:信号从产生到递达之间的状态成为信号未决(Pending)。
- 信号阻塞:进程可以选择阻塞(Block)某个信号。
需要注意的是:
- 被阻塞的信号产生时将保持在未决状态,直到进程解除对该信号的阻塞,才执行递达的动作。
- 阻塞和忽略是不一样的,阻塞是信号还未被处理,而忽略是信号处理的一种方式。
- 所有的信号如果都未被阻塞,那么所有信号将被递达;所有的信号如果都被block,那么一定不会被递达。
在操作系统中的表示:
信号在操作系统底层的表示,如下图:
信号阻塞的相关函数:
sigprocmask
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
作用:读取进程的信号屏蔽字(阻塞信号集)
how:如何更改信号集中的信号,有三个选项
- SIG_BLOCK:设置当前信号屏蔽字的信号
- SIG_UNBLOCK:解除当前信号屏蔽字中阻塞的信号
- SIG_SETMASK:把当前信号屏蔽字设置为什么样子
set:把哪些信号进行设置
oset:把老的block表保存到oldset
返回值:若成功,返回0,失败返回-1
sigpending
int sigpending(sigset_t *set);
- 作用:读取当前进程的信号未决集,通过set参数传出
- set:把哪些信号进行设置
- 返回值:若成功,返回0,失败返回-1
实例代码:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void handler(int signo)
{
printf("AAAAAAA\n", signo);
}
void show(sigset_t *pending)//显示pending表
{
int i = 0;
for (i = 0; i <= 31; i++)
{
if (sigismember(pending, i))//判断i是否在信号集中,如果是,证明该信号已被pending
{
printf("1");
}
else
{
printf("0");
}
}
printf("\n");
}
int main()
{
sigset_t set, oset;
sigemptyset(&set);//初始化set
sigemptyset(&oset);//初始化oset
sigaddset(&set, 2);//把2号信号添加到信号集中
sigprocmask(SIG_SETMASK, &set, &oset);//读取信号集中的信号
signal(2, handler);//捕捉2号信号
sigset_t pending;//定义pending表
int i = 10;
while (1)//不断获取pending表
{
sigpending(&pending);//获得当前进程的pending信号集
show(&pending);//显示pending表
sleep(1);
if ((i--) == 0)//每隔一秒显示一次pending表
{
sigprocmask(SIG_SETMASK, &oset, NULL);//把2号信号从阻塞信号集中去掉
}
}
return 0;
}
执行结果: