文章目录
信号保存
信号产生后,操作系统将信号发给进程,进程就要保存信号。
为什么信号要保存?
因为进程收到信号后,可能在忙其他事情,不会立即处理信号,就产生了时间窗口
相关概念
- 实际处理信号的过程叫信号递达(Delivery)
- 信号产生到处理的过程叫做信号未决(Pending)
- 进程可以==阻塞(Block)==某个信号,
- 被阻塞的信号将保持在未决状态
- 被阻塞和忽略是不一样的,被阻塞是递达不了,忽略是信号递达后的一种处理方式
🚩内核三张表

进程PCB里面指向三张表,一张阻塞表block,一张未决表pending,一张处理方式handler表
阻塞状态信号不会被处理,直到解除阻塞状态
也就是说2号信号会一直保持此状态,直到block解除,pending就会被处理
3号信号block为1,阻塞,现在的状态是从未收到过信号,如果收到信号pending会置1==
每个信号都有自己的默认处理方式

如上上图,1号信号默认处理
2号信号,忽略处理
signal(SIGINT,SIG_DFL); 恢复2号
signal(SIGQUIT,SIG_IGN); 将3号忽略

handler表中存的函数指针,每个函数指针指向一个信号处理方式
c
void printpending(sigset_t &pending)
{
for(int i=31;i>=1;i--)
{
if(sigismember(&pending,i))
{
cout<<1;
}
else{
cout<<0;
}
}
cout<<endl;
}
int main()
{
sigset_t bset , oset;//在栈上开辟空间,属于用户区
sigemptyset(&bset);
sigemptyset(&oset);
sigaddset(&bset,2);//没进入内核,只是把bset这个数设置了
//调用系统调用
sigprocmask(SIG_SETMASK, &bset, &oset); //把2屏蔽了
sigset_t pending;
while(1)
{
int n=sigpending(&pending);
if(n<0)
continue;
printpending(pending);
sleep(1);
}
return 0;
}
sigprocmask(SIG_SETMASK,&bset,&oset);
将阻塞表设为bset,其中上次阻塞表保存在oset,不想保存放nullptr就行

我们可以看到阻塞之后,我们向进程发2号信号,pending挂起
解除阻塞
c
int cnt=0;
while(1)
{
int n=sigpending(&pending);
if(n<0)
continue;
printpending(pending);
sleep(1);
cnt++;
if(cnt==20)
{
cout<<"unlock"<<endl;
sigprocmask(SIG_SETMASK,&oset,nullptr);//解除
}
}

解除后立马终止了
所有信号都能被阻塞吗,肯定不是
c
int main()
{
sigset_t bset , oset;
sigemptyset(&bset);
sigemptyset(&oset);
sigaddset(&bset,2);
for(int i=1;i<=31;i++)
{
sigaddset(&bset,i);
}
sigprocmask(SIG_SETMASK,&bset,&oset);
sigset_t pending;
while(1)
{
int n=sigpending(&pending);
if(n<0)
continue;
printpending(pending);
sleep(1);
}
return 0;
}

