目录
2.信号的保存
2.1信号保存的基本概念
2.2信号在哪里保存的?怎么保存的?
2.3处理信号的三张表
2.4三张表的匹配操作和系统调用接口
2.4.1sigprocmask
2.4.2sigemptyset
2.4.3sigfillset
2.4.4sigaddset&&sigdelset
2.4.5sigismember
2.4.6sigpending
2.5demo代码
细节
2.信号的保存
2.1信号保存的基本概念
处理信号的动作叫做递达(Delivery),处理信号有三种方式,默认,忽略,自定义。
信号从产生到信号递达之间的状态叫做未决(Pending)。
进程可以选择阻塞(Block)某个信号。
2.2信号在哪里保存的?怎么保存的?
信号是在进程pcb中被保存的,也就是task_struct中。
保存的方式采用的是位图。
struct
{
unsigned long int pending;
unsigned long int block;
};
pending:比特位的位置表示信号的编号,比特位的内容表示是否是未决的。
block:比特位的位置表示信号的编号,比特位的内容表示是否是阻塞。
阻塞和忽略不是一个概念
阻塞是阻止信号递达,忽略是递达之后忽略。
2.3处理信号的三张表
block就是block位图,pending就是pending位图,handler是一个函数指针数组。
当进程收到2信号,首先会将pending位图第二比特位变为1,等到机会合适时处理pending中的信号,处理时会看2号信号的位置在block中是否为1,如果为1就阻塞住,不递达,为0就递达,调用handler中对应的函数。
2.4三张表的匹配操作和系统调用接口
2.4.1sigprocmask
查看和修改阻塞信号,就是修改block位图。
how:如何修改
set:信号集
sigset_t类型是一个结构体,__val就是和pending一样的位图。
#define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int)))
typedef struct
{
unsigned long int __val[_SIGSET_NWORDS];
} __sigset_t;
oldset:输出型参数,将未修改之前的位图保存。
返回值
成功返回0,失败返回-1
2.4.2sigemptyset
将参数set初始化,并把所有信号都清空。
2.4.3sigfillset
将set初始化,包含所有信号。
2.4.4sigaddset&&sigdelset
向set信号集中添加或者删除信号,参数signum就是添加几号信号。
2.4.5sigismember
检查set信号集中是否包含signum
包含返回1,不包含返回0,出错返回-1.
2.4.6sigpending
检查pending位图
set是输出型参数。
2.5demo代码
1.屏蔽2号信号
2.打印pending位图中的内容
3.向进程发送2号信号,因为2号信号被阻塞了,所以2号信号会一直在pending位图中。
#include<iostream>
#include<signal.h>
#include<string.h>
#include<cerrno>
void print(sigset_t* s)
{
for(int i = 31; i > 0; i--)
{
if(sigismember(s,i) == 1)
{
std::cout<<"1";
}
else if(sigismember(s,i) == 0)
{
std::cout<<"0";
}
else
{
std::cout<<"sigismember fail:"<<strerror(errno)<<std::endl;
}
}
std::cout<<std::endl;
}
int main()
{
sigset_t s;
sigset_t output;
sigemptyset(&s);
sigaddset(&s,2);
sigprocmask(SIG_SETMASK,&s,&output);
sigset_t pend;
while(true)
{
sigpending(&pend);
print(&pend);
sleep(1);
}
return 0;
}
使用kill命令向进程sigPreserve发送2号信号
pending位图的2号信号位置果然变为1了。
那是不是这个进程把所有的信号都屏蔽了,那这个进程是不是就无敌了我们可以试验一下。
直接将所有信号阻塞,看有没有信号可以杀死该进程。
我们发现,1-8号都成功的被阻塞了,但是9号信号直接杀死了进程。
SIGKILL (9):这是一个强制终止进程的信号,通常由系统管理员或者操作系统自身发送。它无法被阻塞,因为它的目的是强制终止进程,即使进程已经阻塞了所有其他信号。
SIGSTOP (19) 和 SIGCONT (18):SIGSTOP 用于暂停进程的执行,SIGCONT 用于继续执行被暂停的进程。它们也是不可阻塞的,因为它们是用来控制进程执行状态的信号,不受进程阻塞的影响。
细节
1.信号被递达的时候一定会把对应的pending位图清空。
2.先清空pending位图,再递达