阻塞信号集和未决信号集
1、用户通过键盘 Ctrl + C,产生 2 号信号 SIGINT(信号被创建)
2、信号产生但是没有被处理(未决状态)
- 在内核中所有的没有被处理的信号存储在一个集合当中(PCB 当中的未决信号集)
- SIGINT 未决信号,2号信号被存储在第二个标志位上。
- 这个标志位的值为 0 ,说明信号不是未决状态
- 这个标志位的值为 1, 说明信号是未决状态
3、这个未决信号需要被处理,在处理之前需要和另一个信号集(阻塞信号集)进行比较
- 阻塞信号集默认不阻塞任何信号(也是就是阻塞信号集的每一个位置都是 0 。若为 1 ,则表示需要阻塞。)
- 如果想要某些信号需要系统调用 API
4、在处理的时候和阻塞信号集中的标志位进行查询,看该信号是否被设置为阻塞的状态。
- 如果被阻塞了,信号继续处于未决状态,直到阻塞解除,信号就被处理
- 如果信号没有被阻塞,则信号被处理
为什么需要阻塞信号?
程序运行需要符合一定的逻辑(比如一系列动作的原子操作),如果不阻塞,便会影响到阻塞信号的逻辑。
信号集操作相关的函数的系统调用
/*
#include <signal.h>
int sigemptyset(sigset_t *set);
-功能:清空信号集,将信号集中所有的标志位置为 0
(sigset_t 是一个64位的整数)
(我的困惑,为什么不能自己直接手动设置为 0 呢?非得弄一个函数)
-参数:set,传出参数,需要操作的信号集
-返回值:成功0,失败-1并设置错误号erron
int sigfillset(sigset_t *set);
-功能:清空信号集,将信号集中所有的标志位置为 1
(sigset_t 是一个64位的整数)
(我的困惑,为什么不能自己直接手动设置为 0 呢?非得弄一个函数)
-参数:set,传出参数,需要操作的信号集
-返回值:成功0,失败-1并设置错误号erron
int sigaddset(sigset_t *set, int signum);
-功能:设置信号集的某一个标志位为1,表示阻塞这个信号
(sigset_t 是一个64位的整数)
(我的困惑,为什么不能自己直接手动设置为 0 呢?非得弄一个函数)
-参数:set,传出参数,需要操作的信号集
-返回值:成功0,失败-1并设置错误号erron
int sigdelset(sigset_t *set, int signum);
-功能:设置信号集的某一个标志位为0,表示不阻塞这个信号
(sigset_t 是一个64位的整数)
(我的困惑,为什么不能自己直接手动设置为 0 呢?非得弄一个函数)
-参数:set,传出参数,需要操作的信号集
-返回值:成功0,失败-1并设置错误号erron
int sigismember(const sigset_t *set, int signum);
-功能:判断某个信号是否会被阻塞
-参数:set 指定的信号集
signum 需要判断的那个信号
-返回值:1表示被阻塞,0表示不阻塞,-1表示调用失败
上述的信号集都是对自定义的信号进行操作
*/
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
int main(void){
//创建一个新的信号集
sigset_t set;
//清空信号集
int ret = sigemptyset(&set);
if(ret == -1){
perror("sigemptyset");
exit(0);
}
//判断 SIGINT 是否在信号集当中
ret = sigismember(&set,SIGINT);
if(ret == -1){
perror("sigismember-SIGINT");
exit(0);
}
else if(ret == 0){
printf("SIGINT 不阻塞\n");
}
else if(ret == 1){
printf("SIGINT 阻塞\n");
}
//向信号集中加入指定的信号
ret = sigaddset(&set,SIGINT);
if(ret == -1){
perror("sigaddset-SIGINT");
exit(0);
}
ret = sigaddset(&set,SIGQUIT);
if(ret == -1){
perror("sigaddset-SIGQUIT");
exit(0);
}
//判断SIGINT 是否在信号集中
ret = sigismember(&set,SIGINT);
if(ret == -1){
perror("sigismember-SIGINT");
exit(0);
}
else if(ret == 0){
printf("SIGINT 不阻塞\n");
}
else if(ret == 1){
printf("SIGINT 阻塞\n");
}
//判断SIGQUIT 是否在信号集中
ret = sigismember(&set,SIGQUIT);
if(ret == -1){
perror("sigismember-SIGQUIT");
exit(0);
}
else if(ret == 0){
printf("SIGQUIT 不阻塞\n");
}
else if(ret == 1){
printf("SIGQUIT 阻塞\n");
}
//删除一个信号
ret = sigdelset(&set,SIGQUIT);
if(ret == -1){
perror("sigdelset-SIGQUIT");
exit(0);
}
//删完后判断下 SIGQUIT 是否在信号集中
ret = sigismember(&set,SIGQUIT);
if(ret == -1){
perror("sigismember-SIGQUIT");
exit(0);
}
else if(ret == 0){
printf("SIGQUIT 不阻塞\n");
}
else if(ret == 1){
printf("SIGQUIT 阻塞\n");
}
return 0;
}