【linux编程】信号集、sigprocmask、sigpending
信号集、sigprocmask、sigpending
信号源为目标进程产生了一个信号,然后由内核来决定是否要将该信号传递给目标进程。从信号产生到传递给目标进程的流程图如下图所示:

进程可以阻塞信号的传递。当信号源为目标进程产生了一个信号之后,内核会执行依次执行下面操作,
1. 如果目标进程设置了忽略该信号,则内核直接将该信号丢弃。
2. 如果目标进程没有阻塞该信号,则内核将该信号传递给目标进程,由目标进程执行相对应操作。
3. 如果目标进程设置阻塞该信号,则内核将该信号放到目标进程的阻塞信号列表中,等待目标进程对该类型信号的下一步设置。若目标进程后续设置忽略该信号,则内核将该信号从目标进程的阻塞信号列表中移除并丢弃。若目标进程对该信号解除了阻塞,内核将该信号传递给目标进程进行相对应的操作。
在信号产生到信号传递给目标进程之间的时间间隔内,我们称该信号为未决的(pending)。
每个进程都有一个信号屏蔽字(signal mask),它规定了当前要阻塞传递给该进程的信号集。对于每种可能的信号,信号屏蔽字中都有一位与之对应。
1. 信号集:
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) // 将某个信号清出信号集
2. 函数sigprocmask
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
分析:
1. set:传入参数,是一个位图,set中哪个位置置为1,就表示当前进程屏蔽了哪个信号
2. oldset:传出参数,保存旧的信号屏蔽集
3. how参数取值
- SIG_BLOCK:当how设置为此值,set表示需要屏蔽的信号
- SIGB_UNBLOCK:当how设置为此值,set表示需要解除屏蔽的信号
- SIG_SETMASK:当how设置为此值,set表示用于替代原始屏蔽集的新屏蔽集,相当于mask = set,若调用sigprocmask解除了对当前信号若干个信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。
3. 函数sigpendin:读取当前信号的未决信号集
int sigpending(sigset_t *set); //set传出参数
1. 测试代码
1 #include <stdio.h> 2 #include <signal.h> 3 #include <unistd.h> 4 5 void printped(sigset_t *ped) 6 { 7 int i; 8 for (i = 1; i < 32; i++) 9 { 10 if (sigismember(ped, i) == 1) 11 putchar('1'); 12 else 13 putchar('0'); 14 } 15 printf("\n"); 16 } 17 18 int main() 19 { 20 sigset_t myset, oldset, ped; 21 sigemptyset(&myset); 22 sigaddset(&myset, SIGQUIT); // Ctrl + / 23 sigaddset(&myset, SIGINT); // Ctrl + C 24 sigaddset(&myset, SIGTSTP); // Ctrl + Z 25 sigaddset(&myset, SIGSEGV); 26 sigaddset(&myset, SIGKILL); //无法被屏蔽 27 sigprocmask(SIG_BLOCK, &myset, &oldset); 28 while (1) 29 { 30 sigpending(&ped); 31 printped(&ped); 32 sleep(2); 33 } 34 return 0; 35 }
输出结果:

2. 测试代码:
1 #include <unistd.h> 2 #include <signal.h> 3 #include <string.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 7 void handler(int sig) 8 { 9 if (sig == SIGINT) 10 printf("recv a sig = %d\n", sig); 11 else if (sig == SIGQUIT) 12 { 13 sigset_t uset; 14 sigemptyset(&uset); 15 sigaddset(&uset, SIGINT); 16 sigprocmask(SIG_UNBLOCK, &uset, NULL); 17 } 18 } 19 20 void printsigset(sigset_t *set) 21 { 22 int i; 23 for (i = 1; i < 32; ++i) 24 { 25 if (sigismember(set, i)) 26 putchar('1'); 27 else 28 putchar('0'); 29 } 30 printf("\n"); 31 } 32 33 int main(int argc, char *argv[]) 34 { 35 sigset_t pset; 36 sigset_t bset; 37 sigemptyset(&bset); 38 sigaddset(&bset, SIGINT); 39 if (signal(SIGINT, handler) == SIG_ERR) 40 { 41 perror("signal error"); 42 exit(1); 43 } 44 if (signal(SIGQUIT, handler) == SIG_ERR) 45 { 46 perror("signal error"); 47 exit(1); 48 } 49 sigprocmask(SIG_BLOCK, &bset, NULL); 50 for (; ;) 51 { 52 sigpending(&pset); 53 printsigset(&pset); 54 sleep(1); 55 } 56 return 0; 57 }
输出结果:

浙公网安备 33010602011771号