由来:
更改信号屏蔽字可以阻塞或解除阻塞所选择的信号,使用这种技术可以保护不希望由信号中断的代码临界区。
实现:
sigset_t newmask,oldmask;
sigemptyset(&newmask);
sigaddset(&newmask,SIGINT);
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0)
printf("error");
/*critical region of code*/
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0) ///----start
printf("error");
pause(); /*wait for signal to occur*/ ///----end
/*continue processing*/
在critical region内发生的信号(newmask设置的)暂不作处理,sigprocmask(SIG_SETMASK..),返回后会对newmask设置的信号进行处理。
例子说白了就是程序运行到critical region段时,收到的SIGINT信号将推迟sigprocmask(SIG_SETMASK..),返回。
pause(); 在等待信号的发生,但此处会发生问题,如果SIGINT,是在sigprocmask(SIG_SETMASK..)和pause()之间发生,进入pause()后将丢失此信号。
为了纠正此问题,需要在一个原子操作中实现恢复信号屏蔽字,然后使进程睡眠,这种功能由sigsuspend函数提供因此有了sigsuspend函数。(start end 那段变成原子)
sigsuspend(const sigset_t *sigmask)
作用:
1:进程的信号屏蔽字设置为sigmask指向的值,
2:在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程也被挂起。
3:如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回,并且信号屏蔽字设置为调用sigsuspend 之前的值。
使用:
int main(void)
{
sigset_t newmask,oldmask,zeromask;
if(signal(SIGINT,sig_int)==SIG_ERR)
printf("error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask,SIGINT);
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0)
printf("error");
/*critical region of code*/
if(sigsuspend(&zeromask)!=-1) //在此代入三个功能点就可理解。
printf("error");
if(sigprocmask(SIG_SETMASK,&oldmask,NULL)<0)
printf("error");
exit(0);
}
阅读(1002) | 评论(0) | 转发(0) |