Linux日常——信号(2)之阻塞信号
来源:互联网 发布:java读取文件编码格式 编辑:程序博客网 时间:2024/06/05 15:48
阻塞信号
这里我们需要先了解几个基本概念
信号递达(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 *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日常——信号(2)之阻塞信号
- Linux日常——信号(signal)
- Linux入门:信号(二)——阻塞信号
- linux之信号阻塞
- linux信号--阻塞信号
- Linux信号机制之信号阻塞
- linux系统编程之信号(五):信号集操作函数,信号阻塞与未决
- linux系统编程之信号(五):信号集操作函数,信号阻塞与未决
- Linux日常——信号(3)之线程安全和可重入函数
- Linux系统编程(23)——信号的阻塞
- Linux下信号--阻塞信号
- Linux信号处理之阻塞,SIGCHLD
- Linux信号和阻塞
- 【Linux】阻塞信号
- linux系统编程之信号(三):信号的阻塞与未决
- linux系统编程之信号(三):信号的阻塞与未决
- linux系统编程之信号(三):信号的阻塞与未决
- (转载)【linux信号】信号未决与阻塞
- PAT 甲级 1021. Deepest Root(dfs:无向图的最远路径、连通分量个数)
- 监听Apk卸载、改变、及安装
- centos下nginx反向代理
- zeromq源码学习——ypipe
- Java内部类
- Linux日常——信号(2)之阻塞信号
- 链表的创建
- Android listview item删除动画和item排序动画
- 为什么方法中的内部类只能访问final修饰的局部变量
- Java高级类特性一
- 常用办公网站和工具使用
- windows 下redis在后台运行
- AsyncTask
- 辅导报二本v是我的错轻微