一、信号集操作函数
内核通过读取未决信号集来判断信号是否应被处理。信号屏蔽字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 + C
sigaddset(&myset, SIGTSTP); // Ctrl + Z
sigaddset(&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');
else
putchar('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);
}
}
输出结果: