执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。
进程可以选择阻塞(Block)某个信号。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。注意,阻塞和忽略是不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
1:PCB进程控制块中函数有信号屏蔽状态字(block)信号未决状态字(pending)还有是否忽略标志(或是信号处理函数);block状态字、pending状态字 64bit;
2:信号屏蔽状态字(block),1代表阻塞、0代表不阻塞;信号未决状态字(pending)的1代表未决,0代表信号可以抵达了;它们都是每一个bit代表一个信号,比如,bit0代表信号SIGHUP;
3:比如向进程发送SIGINT,内核首先判断信号屏蔽状态字是否阻塞,如果该信号被设为为了阻塞的,那么信号未决状态字(pending)相应位制成1;若该信号阻塞解除,信号未决状态字(pending)相应位制成0;表示信号此时可以抵达了,也就是可以接收该信号了。
4:屏蔽状态字用户可以读写,未决状态字用户只能读;这是信号设计机制。
信号集操作函数,对状态字进行操作(屏蔽状态字和未决状态字):
#include <signal.h> int sigemptyset(sigset_t *set);//将信号集清空,共64bits int sigfillset(sigset_t *set);//将信号集置1 int sigaddset(sigset_t *set, int signum);//将signum对应的位置为1 int sigdelset(sigset_t *set, int signum);//将signum对应的位置为0 int sigismember(const sigset_t *set, int signum);//判断signum是否在该信号集合中,如果集合中该位为1,则返回1,表示位于在集合中
#include <signal.h> int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);参数how有下面三种取值:
#include <signal.h> int sigpending(sigset_t *set);
/************************************************************************* > File Name: block_pending.cpp > Author: > Mail: > Created Time: 2015年12月17日 星期四 17时13分45秒 ************************************************************************/ #include <iostream> #include <signal.h> #include <cstdlib> #include <unistd.h> using namespace std; void handler(int num) { if(num == SIGINT){ cout << "刚才收到了信号SIGQUIT, 取消了阻塞,收到中断信号.." << endl; } else if (num == SIGQUIT){ //将SIGINT信号设置为非阻塞的 sigset_t un_bset; sigemptyset(&un_bset); sigaddset(&un_bset, SIGINT); sigprocmask(SIG_UNBLOCK, &un_bset, NULL); } } void print_pending(sigset_t * pset) { int i = 0; cout << "未决状态字(64位):"; for (i = 1; i <= 64; ++i){ if(sigismember(pset, i)) cout << 1; else cout << 0; if(i % 8 == 0){ cout << " "; } } cout << endl; } int main() { sigset_t bset; sigset_t pset; //设置SIGINT信号 sigemptyset(&bset); sigaddset(&bset, SIGINT); signal(SIGINT, handler); signal(SIGQUIT, handler); //将SIGINT信号设置为阻塞的 sigprocmask(SIG_BLOCK, &bset, NULL); while(1){ //得到未决状态字 sigpending(&pset); //显示未决状态字 print_pending(&pset); sleep(1); } exit(0); }