Linux下的信号(signal)的屏蔽与恢复
信号的表示
我们知道linux下,可以通过kill命令向进程发送信号.
当进程收到信号,执行处理动作被称为递达;
当进程接收到信号,还未来得及处理被称之为未决(pending);
进程可以选择阻塞某个信号,当某个信号被阻塞(block)时,永远不会递达!
因此,与这三种处理相对应,在进程的pcb中,存在三张位图来描述信号相关信息!
block、pending与handler
block是一个位图,如果某个信号block为1,则表示其永远也不会递达,也就是说永远都不会执行handler表中的函数.
pending也是一个位图,如果某个信号pending为1,表示其已经产生,如果为0,表示没有产生.
handler指针数组,表示某个信号处理时的默认动作,SIG_DFL表示默认处理,SIG_IGN表示忽略该信号,其它表示自定义处理.
信号的屏蔽与恢复
知道了这些,我编写了一个程序,来验证一下屏蔽、恢复屏蔽一个信号.
////////////////////////////////////
//文件说明:pending.c
//作者:高小调
//创建时间:2017年06月28日 星期三 15时15分45秒
//开发环境:Kali Linux/g++ v6.3.0
////////////////////////////////////
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
//屏蔽SIGINT
void blockSIGINT(){
sigset_t set;
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigprocmask(SIG_BLOCK,&set,NULL);
}
//恢复SIGINT
void recoverSIGINT(){
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK,&set,NULL);
}
//打印未决表
void printPending(sigset_t *set){
for(int i=1; i<=31; ++i){
if(sigismember(set,i)){
putchar('1');
}else{
putchar('0');
}
}
putchar('\n');
}
void handler(int sig){
printf("the No.%d signal is deliver!\n",sig);
}
int main(){
signal(SIGINT,handler);
int count = 5;
printf("block the SIGINT %ds later!\n",count);
sigset_t set;
sigemptyset(&set);
//先将SIGINT屏蔽掉
while(1){
if(count==0){
blockSIGINT();
printf("SIGINT has benn blocked!\n");
break;
}
sigpending(&set);
printPending(&set);
sleep(1);
--count;
}
//再把它恢复过来
printf("recover the SIGINT %ds later!\n",10-count);
while(1){
if(count==10){
recoverSIGINT();
printf("SIGINT has been recovered!\n");
break;
}
//恢复之前,信号被阻塞,因此如果产生SIGINT信号,将会处于未决状态
sigpending(&set);
printPending(&set);
count++;
sleep(1);
}
while(1);
return 0;
}