信号屏蔽pending

来源:互联网 发布:windows迁移linux 编辑:程序博客网 时间:2024/04/29 20:26

信号的产生

1、键盘产生的信号,只能发送到前台。(如:ctrl+c、ctrl+z、ctrl+\)
2、软硬件的异常。(指针异常、除0等)
3、进程调用kill 命令或kill函数。

在Linux下查看信号 kill -l
这里写图片描述
可以查看共有62个信号。1-31为普通信号,34-64为实时信号

一个进程是或否收到1-31号的信息?用什么数据结构比较好?
答:位图(32个bit位)。其中比特位的位置是信号的编号,内容1收到0没收到

这里写图片描述

这里写图片描述
这里写图片描述
如上图./mysig后就是在前台运行,输入shell命令不能执行,在前台运行的进程可以用Ctrl+c终止进程就相当于给进程发了2号信号。
这里写图片描述
如上图./mysig后就是在后台运行,输入shell命令可以执行,在后台运行的进程用Ctrl+c不能杀死,可以发9号终止进程。如下:
这里写图片描述
其中前台和后台还有区别:
这里写图片描述
有+代表在前台运行,没有+代表在后台运行。


信号的处理

1、忽略
2、默认动作
3、自定义捕捉
默认动作就是接收到信号知道怎么处理,比如指针异常实际就是操作系统检测到异常发给了进程11号信号,除0就是发给了进程8号信号,在进程收到这些信号就终止程序。
自定义捕捉函数:
typedef void (*sighandler_t)(int)
sihhandler signal(int signum,sighandler_t handler)

这里写图片描述

这里写图片描述


信号阻塞

实际执行信号的处理动作称为信号递达。
信号从产生到递达之间的状态称为未决。
信号被阻塞将不能进行递达,除非解除阻塞。

阻塞与忽略是不相同的,阻塞是在递达之前,忽略是在递达之后。

信号在内核中的示意图:
这里写图片描述
其中block和pending都是位图,位图的位置都是信号的编号,block中内容1表示阻塞,0表示未阻塞,pending表中内容1表示收到信号,0表示未收到信号。handler表是函数指针数组。SIG_DFL是默认处理SIG_IGN是忽略,void signal是自定义捕捉。

所以操作系统发信号给进程就是操作系统修改了进程PCB中的pending表对应的bit位。


信号屏蔽

信号集操作函数
sigset_t类型对于每种信号用⼀一个bit表示“有效”或“无效”状态
int sigemptyset(sigset_t *set);//初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信号
 int sigfillset(sigset_t *set);//t初始化set所指向的信号集,使其中所有信号的对应bit置位有效,表示该信号集的有效信号包括系统支持的所有信号
 int sigaddset(sigset_t *set, int signo);//信号集中添加某种有效信号
int sigdelset(sigset_t *set, int signo);//信号集中删除某种有效信号
 int sigismember(const sigset_t *set, int signo); //用于判断一个信号集的有效信号中是否包含某种信号

调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。 
 int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
返回值:若成功则为0,若出错则为-1

how参数:1)SIG_BLOCK添加到当前信号屏蔽字的信号
2)SIG_UNBLOCK从当前信号屏蔽字中解除的信号
3)SIG_SETMASK设置当前信号屏蔽字为set所指向的值
spending()获取pending表
信号屏蔽代码:
这里写图片描述
这里写图片描述
上面第一张图片是打印
第二张图中就是进行屏蔽2号信号。
结果:
(在没发2号信号pending表是全零,发了以后第二个位置变为1,其他都为0,2号信号被屏蔽,所以不能进行递达就有了第二个位置一直为1)
这里写图片描述

信号屏蔽与解除并递达:
这里写图片描述
这里写图片描述
上面第一张图片是打印
第二张图中就是进行屏蔽2号信号,并在count++到10后解除并递达,。
结果:
这里写图片描述

原创粉丝点击