1.信号集的定义
信号集是由位图机制实现的
位图机制是一种数据结构,用于存储和操作大量位(即二进制数)的集合。在计算机科学中,它通常被用于表示布尔值或标志,并且可以有效地压缩空间。
位图由一组按顺序排列的比特(0或1)组成,并使用一个或多个字节来存储。每个比特位置都对应着某些状态、属性或标记,例如“是否启用”、“是否已读取”等等。因此,在许多情况下,我们可以将这些信息编码为单个整数并将其保存在一个数组中。
未决信号集和阻塞信号集
未决信号集(Pending Signal Set)是指正在等待被处理的信号的集合。当一个进程收到一个信号时,该信号会被添加到该进程的未决信号集中,并且只有在进程处理完当前正在进行的操作后才能处理这个未决信号。 阻塞信号集(Blocked Signal Set)则是指一组已经阻塞或者暂停了对应于这些特定类型的信号处理程序执行过程中接受新消息或通知请求的操作系统内部数据结构。
1.用户通过键盘 Ctrl + C, 产生2号信号SIGINT (信号被创建)
2.信号产生但是没有被处理 (未决状态)
- 在内核中将所有的没有被处理的信号存储在一个集合中 (未决信号集)
- SIGINT信号状态被存储在第二个标志位上
- 这个标志位的值为0, 说明信号不是未决状态
- 这个标志位的值为1, 说明信号处于未决状态(此时为1)
3.这个未决状态的信号,需要被处理,处理之前需要和另一个信号集(阻塞信号集),进行比较
- 阻塞信号集默认不阻塞任何的信号
- 如果想要阻塞某些信号需要用户调用系统的API
4.在处理的时候和阻塞信号集中的标志位进行查询,看是不是对该信号设置阻塞了
- 如果没有阻塞(0),这个信号就被处理
- 如果阻塞了(1),这个信号就继续处于未决状态,直到阻塞解除,这个信号就被处理
信号集相关的函数
//前五个可以设置自己定义的信号集
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signum);
int sigdelset(sigset_t *set,int signum);
int sigismember(const sigset_t *set,int signum);
//后面两个可以处理系统内核的信号集
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);
int sigpending(sigset_t *set);
2.处理自定义信号集的一些函数
2.1 sigemptyset函数
功能:清空信号集中的数据,将信号集中的所有的标志位置为0
int sigemptyset(sigset_t *set);
- 参数:set,传出参数,需要操作的信号集
- 返回值:成功返回0, 失败返回-1
2.2 sigfillset函数
功能:将信号集中的所有的标志位置为1
int sigfillset(sigset_t *set);
- 参数:set,传出参数,需要操作的信号集
- 返回值:成功返回0, 失败返回-1
2.3 sigaddset函数
设置信号集中的某一个信号对应的标志位为1,表示阻塞这个信号
int sigaddset(sigset_t *set, int signum);
- 参数:
- set:传出参数,需要操作的信号集
- signum:需要设置阻塞的那个信号
- 返回值:成功返回0, 失败返回-1
2.4 sigdelset函数
功能:设置信号集中的某一个信号对应的标志位为0,表示不阻塞这个信号
int sigdelset(sigset_t *set, int signum);
- 参数:
- set:传出参数,需要操作的信号集
- signum:需要设置不阻塞的那个信号
- 返回值:成功返回0, 失败返回-1
2.5 sigismember函数
功能:判断某个信号是否阻塞,因为不需要改变信号集,参数类型为const
int sigismember(const sigset_t *set, int signum);
- 参数:
- set:需要操作的信号集
- signum:需要判断的那个信号
- 返回值:
1 : signum被阻塞
0 : signum不阻塞
-1 : 失败
测试代码
#include <signal.h>
#include <stdio.h>
int main() {
// 创建一个信号集,传出参数
sigset_t set;
// 可能有默认值,清空信号集的内容
sigemptyset(&set);
// 判断 SIGINT 是否在信号集 set 里,此时不阻塞
int ret = sigismember(&set, SIGINT);
if(ret == 0) {
printf("SIGINT 不阻塞\n");
} else if(ret == 1) {
printf("SIGINT 阻塞\n");
}
// 添加信号到信号集中
sigaddset(&set, SIGINT);
// 判断SIGINT是否在信号集中,此时阻塞
ret = sigismember(&set, SIGINT);
if(ret == 0) {
printf("SIGINT 不阻塞\n");
} else if(ret == 1) {
printf("SIGINT 阻塞\n");
}
// 从信号集中删除信号
sigdelset(&set, SIGINT);
// 判断SIGINT是否在信号集中,此时又不阻塞了
ret = sigismember(&set, SIGINT);
if(ret == 0) {
printf("SIGINT 不阻塞\n");
} else if(ret == 1) {
printf("SIGINT 阻塞\n");
}
return 0;
}