Linux日常——信号(2)之阻塞信号
2017-06-13 21:41
183 查看
阻塞信号
这里我们需要先了解几个基本概念信号递达(Delivery) :实际执⾏行信号的处理动作
信号未决(Pending) :信号从产⽣生到递达之间的状态
阻塞:进程可以选择阻塞 (Block )某个信号。
被阻塞的信号产⽣生时将保持在未决状态,直到进程解除对此信号的阻塞, 才执⾏行递达的动作。
阻塞:在信号未决状态产生,此时没有对信号做出处理
忽略:在信号递达后进行,忽略也是对信号的一种处理方式(就是不做处理-_-)
每个进程的PCB块里都有3张表
block:位图,用于表示信号是否被阻塞(屏蔽)—————-阻塞
pending:位图,用于表示信号是否收到————————-未决
handler:函数指针数组,描述信号被如何处理(3种方式)——-递达
SIG_DFL:默认方式
SIG_ING:忽略方式
在上图的例⼦子中,
1. SIGHUP信号未阻塞也未产⽣生过,当它递达时执⾏行默认处理动作。
2. SIGINT信号产⽣生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在 没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
3. SIGQUIT信号未产⽣生过,⼀一旦产⽣生SIGQUIT信号将被阻塞,它的处理动作是⽤用户⾃自定义函数sighandler。
信号集sigset_t
这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞
( 阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask))
在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。
产生:
Linux中规定::常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。
每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示 。因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集。
信号集操作函数
头文件:signal.c
int sigemptyset(sigset_t *set)
初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信号
int sigfillset(sigset_t *set )
初始化set所指向的信号集,使其中所有信号的对应bit置位(全1),表示该信号集的有效信号包括系统⽀支持的所有信号
在使用sigset_t类型 的变量之前,一定要调用sigemptyset或sigfillset做初始化,使信号集处于确定的状态
int sigaddset(sigset_t *set ,int signo)
向信号集中添加某种有效信号
int sigdelset (sigset_t *
4000
set ,int signo)
向信号集中删除某种有效信号
以上四个函数都是成功返回0,出错返回-1
int sigismember(const sigset_t *set ,int signo )
布尔函数,用于判断一个信号集的有效信号中是否包含某种信号
包含则返回1,不包含则返回0, 出错返回-1
int sigprocmask(int how, const sigset_t *set, sigset_t *oset)
读取或更改进程的信号屏蔽字(阻塞信号集)
成功则为0,若出错则为-1
如果oset是⾮非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。
如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。
如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset⾥里,然后根据set和how参数更改信号屏蔽字。
简单来说:
oset可以用来记录修改前的block,方便执行完操作后恢复之前的block
set是修改后的新block表
how是要执行的操作(3种)
SIG_BLOCK:添加信号到当前的block,mask=mask | set
SIG_UNBLOCK:解除当前block中的信号,mask=mask & ~set
SIG_SRTMASK:设置当前block为set指向的值, mask=set
解释:
mask是当前block表。它在oset中做备份,而set是新的block表,set与mask做运算
以下是实现进程
在10秒内,block表屏蔽2号信号,此时间段内从键盘发送一个2号信号,pending表被设置,但信号却不会被递达,10秒结束后恢复到原来状态,信号被捕获(信号递达)
#include<stdio.h> #include<signal.h> void showpending(sigset_t *pending) { int i=1; for(;i<=31;++i) { //判断i号信号是否存在于pending if(sigismember(pending,i)) { printf("1"); } else{ printf("0"); } } printf("\n"); } void handler(int sig) { printf("get a sig :%d\n",sig); } int main() { sigset_t blockset,oblockset,pending; //设置3张表,新的block表,旧block //初始化两张表,全置0 sigemptyset(&blockset); sigemptyset(&oblockset); //向block中添加2号信号,---屏蔽2号 sigaddset(&blockset,2); signal(2,handler); //备份原来的block(oblockset是备份),向blockset中设置屏蔽2号信号 sigprocmask(SIG_SETMASK,&blockset,&oblockset); int count=1; while(1) { //获取pending sigpending(&pending); //打印pending showpending(&pending); sleep(1); if((count++)==10) { printf("return old blockset\n"); //恢复为原来的pending sigprocmask(SIG_SETMASK,&oblockset,NULL); } } }
运行结果:
相关文章推荐
- linux 信号简介三 信号阻塞处理
- C语言&nbsp;linux信号和阻塞&nbsp;sigaction…
- Linux Linux程序练习十三(信号阻塞,捕获)
- Linux入门:信号(二)——阻塞信号
- Linux下信号--阻塞信号
- Linux信号和阻塞
- 【Linux】信号的阻塞和递达
- linux系统编程之信号(三):信号的阻塞与未决
- linux基础——linux下五种IO模型小结(阻塞IO、非阻塞IO、IO复用、信号驱动式IO、异步IO)
- Linux日常——信号(3)之线程安全和可重入函数
- (转载)【linux信号】信号未决与阻塞
- 十七、Linux系统编程-信号(四)信号在内核中表示、信号的阻塞和未决
- Linux 2.6 Alarm信号中断遇上函数阻塞
- Linux 信号详解五(信号阻塞,信号未决)
- linux 信号 --- 产生 阻塞 捕捉
- Linux信号和阻塞
- linux下的信号阻塞
- linux信号的阻塞和未决
- linux信号阻塞与未决
- linux中信号的产生 阻塞与捕捉