示例代码及执行结果
void sig_int(int);
void sig_usr(int);
int main(){
print_mask("at the beginning:");
sigset_t new_mask,old_mask,wait_mask;
//install signal SIGINT handler
if(signal(SIGINT,sig_int) == SIG_ERR){
//signal error
}
//install signal SIGUSR1 SIGUSR2 handler
if(signal(SIGUSR1,sig_usr) == SIG_ERR){
//signal error
}
if(signal(SIGUSR2,sig_usr) == SIG_ERR){
//signal error
}
//block the signal SIGINT
//protect critical region of code from being interrupted by signal SIGINT
sigemptyset(&new_mask);
sigaddset(&new_mask,SIGINT);
if(sigprocmask(SIG_BLOCK,&new_mask,&old_mask) == -1){
//sigprocmask error
}
print_mask("after block the SIGINT and before the sigsuspend:");
/*
critical region of code being protected from being interrupted by signal SIGINT
*/
//reset signal mask to wait_mask instead of adding wait_mask to original mask and wait for a signal to interrupt it and continue the program
//test the signal mask before the sigsuspend returns(caught a signal and being exectuted the handler)
sigemptyset(&wait_mask);
sigaddset(&wait_mask,SIGUSR1);
//SIGUSR1 is blocked, all signals except SIGUSR1 are allowed to interrupt the suspend and makes the sigsuspend function return
//when program is being suspended by function sigsuspend, the signal which is not blocked will be delivered and handled, and the current signal mask includes wait_mask and itself, the sigsuspend will return -1 after the handling
if(sigsuspend(&wait_mask) != -1){
//sigsuspend error
}
//after the sigsuspend returns, the signal mask will restore to what is was before the sigsuspend was executed
//check the signal mask
print_mask("after sigsuspend:");
//restore the mask to what it was before the program started and check the result after restoring
if(sigprocmask(SIG_SETMASK,&old_mask,NULL) == -1){
//sigprocmask error
}
print_mask("at the end:");
exit(0);
}
//the signal which is being handled by its handler will be added to the signal mask automatically to prevent being interrupted by the same signal
//SIGINT handler
void sig_int(int signo){
print_mask("\nin sig_int:"); //check the siganl mask
}
//SIGUSR1 handler
void sig_usr(int signo){
if(signo == SIGUSR1)
print_mask("\nSIGUSR1 is being handled and the signal mask is"); //check the siganl mask
if(signo == SIGUSR2)
print_mask("\nSIGUSR2 is being handled and the signal mask is"); //check the siganl mask
}
make生成执行文件sigsuspend
, 执行命令./sigsuspend &
让该可执行文件在后台运行, shell返回结果如下
根据shell返回的进程号24099
,执行命令kill -USR2 24099
向该进程发送SIGUSR2信号, shell返回结果如下
执行结果分析
wait_mask
只包含了SIGUSR1
信号, 所以sigsuspend函数设置signal mask时只屏蔽了SIGUSR1
, 其他的信号都会正常响应, 所以在suspend期间, 我们往该进程发送了SIGUSR2
信号后, 信号会立即被响应, 执行相应的信号处理程序. 在SIGUSR2
的信号处理程序中我们返回了此时进程的信号屏蔽字, 结果是{SIGUSR1 SIGUSR2}
, 证实了sigsuspend函数改变了信号屏蔽字使其只包含了SIGUSR1
, 而SIGUSR2
之所以会出现在信号屏蔽字的原因是在一个信号被处理的过程中(正在执行信号处理程序), 该信号会被加入信号屏蔽字, 即在该信号被处理完成之前, 相同的信号会被屏蔽掉以保证此信号完整的被处理完(信号处理程序被执行完)
结论
- sigsuspend函数不是在原来的信号屏蔽字的基础上再屏蔽给定的mask里的信号, sigsuspend会完全按照给定的mask改变信号屏蔽字
- 当sigsuspend函数正在使程序suspend时, 没有被sigsuspend屏蔽的信号到达时, 会立刻被响应并执行相应的信号处理程序, 信号处理程序执行的过程中该信号会被加入到信号屏蔽字, 信号处理程序执行完毕后, sigsuspend函数会返回
- sigsuspend函数返回后, 信号屏蔽字会恢复到sigsuspend函数执行前的值
- 当sigsuspend函数正在使程序suspend时, 如果被sigsuspend函数屏蔽的信号被发送, 这些信号何时被处理, 如果屏蔽的信号有很多种, 而且这些信号都发送了, 这些信号被处理的顺序是怎样的, 请看我的这篇文章当sigsuspend函数正在使程序suspend时, 如果被sigsuspend函数屏蔽的信号被发送, 这些信号何时被处理, 如果屏蔽的信号有很多种, 而且这些信号都发送了, 这些信号被处理的顺序