一、信号集操作函数
内核通过读取未决信号集来判断信号是否应被处理。信号屏蔽字mask可以影响未决信号集。而我们可以在用程序自定义set来改变mask,来达到屏蔽指定信号目的。
sigset_t set; // typedef unsigned long sigset_t
int sigemptyset(sigset_t *set) // 将某个信号集清0
int sigfillset(sigset_t *set) // 将某个信号集置1
int sigaddsetset(sigset_t *set, int sino) // 将某个信号加入信号集
int sigdelset(sigset_t *set, int signo) // 将某个信号清出信号集
int sigismember(cosnt sigset_t *set, int signum); // 判断某个信号是否在信号集中
二、函数sigprocmask
1. 函数原型:用来屏蔽信号、解除信号屏蔽使用该函数,其本质,读取或修改进程的信号屏蔽字(PCB)
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
分析:
- set:传入参数,是一个位图,set中哪个位置置为1,就表示当前进程屏蔽了哪个信号
- oldset:传出参数,保存旧的信号屏蔽集
- how参数取值
how | 说明 |
---|---|
SIG_BLOCK | 当how设置为此值,set表示需要屏蔽的信号 |
SIGB_UNBLOCK | 当how设置为此值,set表示需要解除屏蔽的信号 |
SIG_SETMASK | 当how设置为此值,set表示用于替代原始屏蔽集的新屏蔽集,相当于mask = set,若调用sigprocmask解除了对当前信号若干个信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。 |
严格注意,屏蔽信号:只是将信号处理延后执行(延至解除屏蔽);而忽略表示将信号丢处理
三、函数sigpending
函数作用:读取当前信号的未决信号集
int sigpending(sigset_t *set); //set传出参数
四、程序清单
1. 测试代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>void printped(sigset_t *ped)
{int i;for (i = 1; i < 32; i++) {if (sigismember(ped, i) == 1) putchar('1');else putchar('0');}printf("\n");
}int main()
{sigset_t myset, oldset, ped;sigemptyset(&myset);sigaddset(&myset, SIGQUIT); // Ctrl + /sigaddset(&myset, SIGINT); // Ctrl + Csigaddset(&myset, SIGTSTP); // Ctrl + Zsigaddset(&myset, SIGSEGV);sigaddset(&myset, SIGKILL); //无法被屏蔽sigprocmask(SIG_BLOCK, &myset, &oldset);while (1) {sigpending(&ped);printped(&ped);sleep(2);}return 0;
}
输出结果:
2. 测试代码
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>void handler(int sig);void printsigset(sigset_t *set)
{int i;for (i = 1; i < 32; ++i) {if (sigismember(set, i))putchar('1');elseputchar('0');}printf("\n");
}int main(int argc, char *argv[])
{sigset_t pset;sigset_t bset;sigemptyset(&bset);sigaddset(&bset, SIGINT);if (signal(SIGINT, handler) == SIG_ERR) {perror("signal error");exit(1);}if (signal(SIGQUIT, handler) == SIG_ERR) {perror("signal error");exit(1);}sigprocmask(SIG_BLOCK, &bset, NULL);for (; ;) {sigpending(&pset);printsigset(&pset);sleep(1);}return 0;
}void handler(int sig)
{if (sig == SIGINT)printf("recv a sig = %d\n", sig);else if (sig == SIGQUIT) {sigset_t uset;sigemptyset(&uset);sigaddset(&uset, SIGINT);sigprocmask(SIG_UNBLOCK, &uset, NULL);}
}
输出结果: