完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
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 《signal.h》 int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 返回值:若成功则为0,若出错则为-1 (1)如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。(2)如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。(3)如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。 SIG_BLOCK set包含了我们希望添加到当前信号屏蔽字的信号,相当于mask=mask|set SIG_UNBLOCK set包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set SIG_SETMASK 设置当前信号屏蔽字为set所指向的值,相当于mask=set 例子: /* *程序运行时,每秒钟把各信号的未决状态打印一遍,由于我们阻塞了SIGINT信号, *按Ctrl-C将会使SIGINT信号处于未决状态, *按Ctrl-仍然可以终止程序,因为SIGQUIT信号没有阻塞。 * *book@ubuntu:~$ 。/app *0000000000000000000000000000000 *0000000000000000000000000000000(这时按Ctrl-C) *0100000000000000000000000000000 *0100000000000000000000000000000(这时按Ctrl-) *Quit (core dumped) * *或者按下Ctrl-C十秒之后也会推出,这就是main函数中的while中的代码的作用 */ #include 《signal.h》 #include 《stdio.h》 void printsigset(const sigset_t *set) { int i; for (i = 1; i 《 32; i++)//从1号信号开始检测 if (sigismember(set, i) == 1)//测试i号位知否置1 putchar(‘1’); else putchar(‘0’); puts(“”);//打印换行 } int main(void) { int i = 0; sigset_t s, p; //定义两个信号集 每一个信号集的大小是128Byte sigemptyset(&s);//将信号集s全部信号位置0 sigaddset(&s, SIGINT);//将s信号集中的SIGINT信号位(即2号位)置1 sigprocmask(SIG_BLOCK, &s, NULL);//将s信号集合原有信号集做或操作(由第一个参数决定更改方式) while (1) { sigpending(&p);//获取当前进程未决信号集 printsigset(&p);//打印未决信号集 if(i == 10)//10秒后释放对SIGINT信号的阻塞 { sigprocmask(SIG_UNBLOCK, &s, NULL); } sleep(1); i++; } return 0; } 2、sigpending sigpending读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。 #include 《signal.h》 int sigpending(sigset_t *set); |
|
|
|
只有小组成员才能发言,加入小组>>
1907个成员聚集在这个小组
加入小组我的项目我做主,使用GN+Ninja来完成构建系统(VSCode开发RT106X)
36358 浏览 0 评论
NXP IMX8应用处理器快速入门必备:技巧、使用、设计指南
4396 浏览 0 评论
6050 浏览 1 评论
6763 浏览 0 评论
NXP i.MX6UL开发板(linux系统烧录+规格+硬件+模块移植)使用手册
4213 浏览 0 评论
619浏览 2评论
求助,S32G上Core M启动后如何让Core A在Flash指定位置加载uboot?
614浏览 2评论
ESP32-WROVER-IE + LAN8720以太网,GPIO0电压只有1.6v,无法正常进入spi flash boot模式如何解决?
606浏览 2评论
求分享适用于PN7160 Android的NFC工厂测试应用程序
694浏览 2评论
798浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 20:33 , Processed in 0.993057 second(s), Total 80, Slave 63 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号