信号的阻塞:通过sigprocmask()将信号集sigset_t中的信号设置为阻塞。SIG_BLOCK是指对相应信号的“递送阻塞”,内核在递送一个原来被阻塞的信号给进程时(而不是在产生该信号时),才决定对它的处理方式,那么进程在信号递送给它之前仍可改变对该信号的动作。
一个信号的"生命周期"为:产生(generation)、未决(pending)、递送(delivery)
如果将信号设置为阻塞,那么,在信号产生和递送之间的时间间隔内,称信号是未决的(pending)。
如果信号被设置成阻塞,且该信号的动作是系统默认动作或捕获该信号,当该信号产生后,则进程将此信号的状态保持为未决(pending)状态,直到对该信号解除了阻塞或将该信号的动作改为忽略。
sigpending函数的作用是获取被设置为SIG_BLOCK的信号集。
1 static void sig_quit(int signo) 2 { 3 printf("111caught SIGQUIT\n"); 4 if (signal(SIGQUIT, SIG_DFL)==SIG_ERR) 5 { 6 printf("can‘t reset SIGQUIT\n"); 7 } 8 }
1 int main(int argc, char** argv) 2 { 3 sigset_t newmask, oldmask, pendmask; 4 5 if (signal(SIGQUIT, sig_quit) == SIG_ERR) 6 { 7 printf("can‘t catch SIGQUIT\n"); 8 return -1; 9 } 10 11 //block SIGQUIT and save cureent signal mask 12 sigemptyset(&newmask); 13 sigaddset(&newmask, SIGQUIT); 14 15 if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)//阻塞SIGQUIT信号 16 { 17 printf("SIGBLCOK error\n"); 18 return -1; 19 } 20 printf("newmask:%x, oldmask:%x\n", newmask, oldmask); 21 22 sleep(5); 23 24 if (sigpending(&pendmask)<0) 25 { 26 printf("sigpending error\n"); 27 return -1; 28 } 29 printf("pendmask:%x\n", pendmask); 30 31 if (sigismember(&pendmask, SIGQUIT)) 32 printf("SIGQUIT pending\n"); 33 34 if (sigprocmask(SIG_SETMASK, &oldmask, NULL))//解除阻塞 35 { 36 printf("sigprocmask error\n"); 37 return -1; 38 } 39 printf("222SIGQUIT unblock\n"); 40 41 sleep(5); 42 43 return 0; 44 }
运行结果为:
1. 当在第一个sleep 5s期间,Ctrl+\ 产生SIGQUIT信号时:
因为在sleep期间产生了SIGQUIT信号,那么此时该信号的状态时pending的,当该信号被设置为不阻塞后,即解除阻塞后,立即捕获该信号。从输出中可以看出,sig_quit中的printf语句先执行,然后再执行sigprocmask之后的printf语句。
2. 如果在第一个sleep 5s期间,不产生SIGQUIT信号,显然,sigpending的输出为0。
从结果中可以看到,本次pendmask为0,而上次pendmask为4。
SIG_BLOCK是指对相应信号的“递送阻塞”,内核在递送一个原来被阻塞的信号给进程时(而不是在产生该信号时),才决定对它的处理方式,那么进程在信号递送给它之前仍可改变对该信号的动作。
1 static void sig_quit(int signo) 2 { 3 printf("111caught SIGQUIT\n"); 4 if (signal(SIGQUIT, SIG_DFL)==SIG_ERR) 5 { 6 printf("can‘t reset SIGQUIT\n"); 7 } 8 }
1 static void sig_quit2(int signo) 2 { 3 printf("xxxcaught SIGQUIT\n"); 4 if (signal(SIGQUIT, SIG_DFL)==SIG_ERR) 5 { 6 printf("can‘t reset SIGQUIT\n"); 7 } 8 }
1 int main(int argc, char** argv) 2 { 3 sigset_t newmask, oldmask, pendmask; 4 5 if (signal(SIGQUIT, sig_quit) == SIG_ERR) 6 { 7 printf("can‘t catch SIGQUIT\n"); 8 return -1; 9 } 10 11 //block SIGQUIT and save cureent signal mask 12 sigemptyset(&newmask); 13 sigaddset(&newmask, SIGQUIT); 14 15 if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)//阻塞SIGQUIT信号 16 { 17 printf("SIGBLCOK error\n"); 18 return -1; 19 } 20 printf("newmask:%x, oldmask:%x\n", newmask, oldmask); 21 22 sleep(5); 23 24 if (signal(SIGQUIT, sig_quit2) == SIG_ERR) 25 { 26 printf("can‘t catch SIGQUIT\n"); 27 return -1; 28 } 29 30 if (sigpending(&pendmask)<0) 31 { 32 printf("sigpending error\n"); 33 return -1; 34 } 35 printf("pendmask:%x\n", pendmask); 36 37 if (sigismember(&pendmask, SIGQUIT)) 38 printf("SIGQUIT pending\n"); 39 40 if (sigprocmask(SIG_SETMASK, &oldmask, NULL)) 41 { 42 printf("sigprocmask error\n"); 43 return -1; 44 } 45 printf("222SIGQUIT unblock\n"); 46 47 sleep(5); 48 49 return 0; 50 }
运行结果为:
在line24中,又重新设置的SIGQUIT的信号处理程序。
如果信号被设置成阻塞,且该信号的动作是系统默认动作或捕获该信号,当该信号产生后,则进程将此信号的状态保持为未决(pending)状态,直到对该信号解除了阻塞或将该信号的动作改为忽略。
1 int main(int argc, char** argv) 2 { 3 sigset_t newmask, oldmask, pendmask; 4 5 if (signal(SIGQUIT, sig_quit) == SIG_ERR) 6 { 7 printf("can‘t catch SIGQUIT\n"); 8 return -1; 9 } 10 11 //block SIGQUIT and save cureent signal mask 12 sigemptyset(&newmask); 13 sigaddset(&newmask, SIGQUIT); 14 15 if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)//阻塞SIGQUIT信号 16 { 17 printf("SIGBLCOK error\n"); 18 return -1; 19 } 20 printf("newmask:%x, oldmask:%x\n", newmask, oldmask); 21 22 sleep(5); 23 24 if (sigpending(&pendmask)<0) 25 { 26 printf("sigpending error\n"); 27 return -1; 28 } 29 printf("pendmask:%x\n", pendmask); 30 31 if (sigismember(&pendmask, SIGQUIT)) 32 printf("SIGQUIT pending\n"); 33 34 if (signal(SIGQUIT, SIG_IGN) == SIG_ERR) 35 { 36 printf("can‘t catch SIGQUIT\n"); 37 return -1; 38 } 39 printf("SIGQUIT IGNORE"); 40 41 sleep(5); 42 43 return 0; 44 }
运行结果为: