Linux----信号屏蔽与解除并递达
来源:互联网 发布:js上拉加载更多 编辑:程序博客网 时间:2024/05/29 12:15
先介绍有关信号的三个概念:
- 信号未决(pending):信号从产生到递达之间的状态。
- 信号递达(delivery):实际执行信号的处理动作。
- 信号阻塞(block):进程可以选择阻塞某个信号。被阻塞的信号将保持在未决状态,知道解除阻塞,才执行递达的动作。
注意:信号阻塞和忽略信号的区别:
只要信号被阻塞就不会被递达。而忽略信号时在递达之后的一种处理动作。
信号在内核中的表示示意图如下:
block:阻塞集信号。用位图表示,只需4字节。位图的下标表示信号的编号,内容为1,表示该信号阻塞,为0,表示该信号非阻塞。
pending:未决信号集。用位图表示,只需4字节。位图的下标表示信号的编号,内容为1,表示收到该信号,为0,表示未收到该信号。
handler:递达。设置对应信号的处理方式,SIG_DFL:表示默认。SIG_IGN:表示忽略。还可选择相应的处理函数指针。
例如说图中的2号信号。收到了2号信号,但是2号信被阻塞,不能递达。该信号递达为忽略。
未决和阻塞标志可以⽤用相同的数据类型sigset_t来存储,sigset_t称为信号集。
阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask), 这里的“屏蔽”应该理解为阻塞⽽而不是忽略。
下面介绍信号集的操作函数:
int sigemptyset(sigset_t *set); //将信号集清零
int sigfillset(sigset_t *set); //将信号集置位
int sigaddset(sigset_t *set, int signo);// 添加某种有效信号
int sigdelset(sigset_t *set, int signo); //删除某种有效信号
int sigismember(const sigset_t *set, int signo); //判断某种信号是否在该信号集里
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); //读取或更改信号的屏蔽字(阻塞信号集)
如果oset是⾮非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是⾮非空指 针,则 更改进程的信号屏蔽字,参数how指⽰示如何更改。如果oset和set都是⾮非空指针,则先 将原来的信号 屏蔽字备份到oset⾥里,然后根据set和how参数更改信号屏蔽字。假设当前的 信号屏蔽字为mask,下表说明了how参数的可选值。
how可选值如下:
SIG_BLOCK:mask=mask|set
SIG_UNBLOCK:mask=mask&~set
SIG_SETMASK:mask=set
如果调⽤用sigprocmask解除了对当前若⼲干个未决信号的阻塞,则在sigprocmask返回前,⾄至 少将其中 一个信号递达。
int sigpending(sigset_t *set);//读取当前进程的未决信号集,通过set参数传出。
以上几个函数头文件为:signal.h
以下举几个例子说明信号的屏蔽,解除后会递达的:
例:测试几个函数,屏蔽2号信号后,当捕捉到2号信号后,观察未决信号集的内容。1 #include<stdio.h>
2 #include<signal.h>
3 void showpending(sigset_t* pending)//打印pending信号集
4 {
5 int i=1;
6 for(;i<=31;i++)
7 {
8 if(sigismember(pending,i))//如果i信号在pending信号集中
9 printf("1");//打印1
10 else//如果i信号在pending信号集中
11 printf("0");//打印0
12
13 }
14 printf("\n");//使得上面的数据从缓冲区打印到显示器上
15
16 }
17
18 int main()
19 {
20 sigset_t blockset,oldblockset,pending;//分别设置一个阻塞信号集,旧的阻塞信号集,未决信号集
21 sigemptyset(&blockset);//将信号集清零
22 sigemptyset(&oldblockset); //将信号集清零
23sigaddset(&blockset,2);//给blockset信号集添加2号信号
25 sigprocmask(SIG_SETMASK,&blockset,&oldblockset);//将旧的阻塞集保存到oldblockset中,将新的阻塞集blockset通过SIG_SETMASK方法设置到PCB的阻塞集中(即就是将2号信号屏蔽)
26 while(1)
27 {
28 sigpending(&pending);//获取未决信号集
29 showpending(&pending);//打印未决信号集
30 sleep(1);//睡眠1s
31 }
32 return 0;
33 }
结果为:
结果分析:符合预期。不断的获取未决信号集pending,发送2号信号后,pending信号集中第二个bit位为1.其他为0.
例:测试几个函数,捕捉信号,屏蔽2号信号后,count累加为5时,恢复之前的阻塞集。在count为5之前,当捕捉到2号信号后,观察未决信号集的内容;在count为5之后,当捕捉到2号信号后,观察未决信号集的内容
1 #include<stdio.h> 2 #include<signal.h> 3 void showpending(sigset_t* pending)//打印pending信号集 4 { 5 int i=1; 6 for(;i<=31;i++) 7 { 8 if(sigismember(pending,i))//如果i信号在pending信号集中 9 printf("1");//打印1 10 else//如果i信号在pending信号集中 11 printf("0");//打印0 12 13 } 14 printf("\n");//使得上面的数据从缓冲区打印到显示器上 15 16 } 17 void handler(int sig) 18 { 19 printf("get a sig:%d\n",sig); 20 } 18 int main() 19 { 20 sigset_t blockset,oldblockset,pending;//分别设置一个阻塞信号集,旧的阻塞信号集,未决信号集 21 sigemptyset(&blockset);//将信号集清零 22 sigemptyset(&oldblockset); //将信号集清零 23sigaddset(&blockset,2);//给blockset信号集添加2号信号signal(2,handler); 25 sigprocmask(SIG_SETMASK,&blockset,&oldblockset);//将旧的阻塞集保存到oldblockset中,将新的阻塞集blockset通过SIG_SETMASK方法设置到PCB的阻塞集中(即就是将2号信号屏蔽)30 int count=0; 26 while(1) 27 { 28 sigpending(&pending);//获取未决信号集 29 showpending(&pending);//打印未决信号集 30 sleep(1);//睡眠1s if((count++)==5) 37 { 38 printf("proc recover\n"); 39 sigprocmask(SIG_SETMASK,&oldblockset,NULL); 40 } 31 } 32 return 0; 33 }
例3,实现1-9s内2号信号被阻塞,10-19s内2号信号被释放,20S后2号信号被阻塞,观察pending信号集
结果为:
阅读全文
0 0
- Linux----信号屏蔽与解除并递达
- 测试信号屏蔽与解除并递达
- 信号屏蔽与信号递达
- linux信号集与信号屏蔽字
- 信号集与屏蔽信号
- linux 信号屏蔽
- linux信号屏蔽字
- Linux--信号屏蔽
- linux信号屏蔽
- Linux网络编程--信号阻塞与屏蔽(block,unblock)
- 【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 信号集与屏蔽信号
- linux进程中的信号屏蔽
- linux之信号屏蔽pending
- Linux中如何屏蔽信号
- Linux c 屏蔽信号、切换信号
- 信号集与屏蔽字
- 阻塞信号与信号屏蔽pending
- Linux Signal (6): 信号屏蔽字
- 布萌区块链使用指南:内有N多“踏坑”经验(多图)
- iOS开发-数组本地存储, JSONModel本地储存实现
- 软件工程第一章知识点总结
- redis的密码设置(2 section)
- 002-Apache Maven 构建生命周期
- Linux----信号屏蔽与解除并递达
- java中String stringBuffer StringBuider
- MySQL命令行大全
- EXE与SYS通信(缓冲模式)
- php屏蔽页面刷新对计数器的影响
- redis 的用法和使用场景
- CAD DLL发布v12新版本,支持最新版本的DWG
- androidannotations注解配置
- 快速下载和编译Dragonboard410c官网最新Android版本