一.信号其他相关常见概念
1.实际执行信号的处理动作称为信号递达
(Delivery)
2.信号从产生到递达之间的状态
,
称为信号未决
(Pending)
。
3.进程可以选择阻塞
(Block )
某个信号。
4/被阻塞的信号产生时将保持在未决状态
,
直到进程解除对此信号的阻塞
,
才执行递达的动作
.
注意
,
阻塞和忽略是不同的
,
只要信号被阻塞就不会递达
,
而忽略是在递达之后可选的一种处理动作。
2.
在内核中的表示
信号在内核中的表示示意图
block:信号有无被堵塞,1表示被堵塞,0表示未被堵塞
pending:表示该进程有无接受到这个信号,1表示接受到这个信号,0表示为接受到这个信号
handler: 信号的处理方法SIL_DFL代表默认处理方法,SIG_IGN代表忽略该信号,User Space代表用户自定义的方法
3. sigset_t
sigset_t是操作系统定时的一种数据结构(本质是位图),与上图的block 和 spending相对应sigset_t做前者被称为
信号屏蔽字,做后者被称为信号集
4.
信号集操作函数
sigset_t
类型对于每种信号用一个
bit
表示
“
有效
”
或
“
无效
”
状态
,
至于这个类型内部如何存储这些
bit则依赖于系统实现
,
从使用者的角度是不必关心的
,
使用者只能调用以下函数来操作
sigset_ t
变量
,而不应该对它的内部数据做任何解释
,
比如用
printf
直接打印
sigset_t
变量是没有意义的
#include <signal.h>
int sigemptyset(sigset_t *set);
作用:函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有效信号
返回值:成功返回0,失败返回-1,并设置相关错误码
int sigfillset(sigset_t *set);
作用:
函数
sigfillset
初始化
set
所指向的信号集
,
使其中所有信号的对应
bit
置位
,表示 该信号集的有效信号包括系统支持的所有信号。
返回值:成功返回0,失败返回-1,并设置相关错误码
int sigaddset (sigset_t *set, int signo);
作用:添加有效信号
返回值:
成功返回0,失败返回-1,并设置相关错误码
int sigdelset(sigset_t *set, int signo);
作用:删除有效信号
返回值:
成功返回0,失败返回-1,并设置相关错误码
int sigismember
(
const sigset_t *set, int signo);
作用:查找set中是否有相关的信号
返回值:有相关信号返回1,没有相关信号返回0,查找失败返回-1,并设置相关的错误码
5.信号屏蔽字的设置
sigprocmask函数
原型:
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
参数:
how :处理模式,有三种
set:设置堵塞时的参考数据
oset:输出型参数,可以获取修改之前的堵塞表,如果置为nullptr则代表忽略原本数据
注意:9号信号是不能被设置为堵塞状态,也不能被用户自定义
6.未执行信号查看
#include <signal.h>
int sigpending(sigset_t *set);
作用:读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1,并设置相关的错误码
参数:
set:输出型参数该函数会把未执行的信号集存储到set中。
上述所有函数在代码中的使用如下:
#include <csignal>
#include <iostream>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
int main()
{
// 先定义一个被系统调用接口需要的数据类型
sigset_t set;
sigset_t set1;
// 初始化变量,是其中的相关数值明确(本次初始化把所有存在标志全部置为无)
int n = sigemptyset(&set);
assert(n != -1);
// 对该变量中插入相关变量
n = sigaddset(&set, 2);
assert(n != -1);
n = sigaddset(&set, 3);
assert(n != -1);
// 删除该变量中的相关信号
n = sigdelset(&set, 3);
assert(n != -1);
// 设置相关的堵塞(这里我们选择覆盖模式,即新的set覆盖老的set,第三个参数置为空,即对老的set忽视)
n = sigprocmask(SIG_SETMASK, &set, nullptr);
assert(n != -1);
// 获取为被执行的信号集,并且循环查看
while (true)
{
sigemptyset(&set1);
n = sigpending(&set1);
assert(n != -1);
for(int i=0;i<=31;i++)
{
if(sigismember(&set1,i)==1)
std::cout<<1;
else
std::cout<<0;
}
std::cout<<"我的pid:"<<getpid();
std::cout<<std::endl;
sleep(1);
}
}
运行结果: