#include static void sig_quit(int);
int main(void)
{
sigset_t newmask, oldmask, pendmask;
if(signal(SIGQUIT, sig_quit) == SIG_ERR)
{
printf("can not catch SIGQUIT");
exit(1);
}
sigemptyset(&newmask);//使用前先设置sigset_t结构
sigaddset(&newmask, SIGQUIT);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)//设置阻塞信号
{
printf("sig_block error");
exit(1);
}
sleep(5);//在5秒内按下键盘上“ctrl” + “\”,会产生SIGQUIT信号,这时候这个信号就是已经发出,但是被阻塞,未决的信号
if(sigpending(&pendmask) < 0)
{
printf("sigpending error");
exit(1);
}
if(sigismember(&pendmask, SIGQUIT))
{
printf("\nSIGQUIT pending\n");//这里会打印信息,说明信号未决
}
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)//回复默认信号动作,执行这个程序的时候,会发现先打印信号处理函数中的内容,再打印下面的内容,从而证明了上面对sigprocmask函数的说明。
{
printf("SIG_SETMASK error");
exit(1);
}
printf("sigquit unblocked\n");
sleep(5);
exit(0);
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT\n");
if(signal(SIGQUIT, SIG_DFL) == SIG_ERR)
{
printf("can not reset sigquit\n");
exit(1);
}
}
六 sigsuspend函数
更改信号屏蔽字可以阻塞所选信号,或解除对它们的阻塞。使用这种技术可以保护部希望由信号中断的代码区域。
如果希望对一个信号解决阻塞,然后pause以等待以前被阻塞的信号,如何实现呢?
sigset_t newmask, oldmask;
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
exit(1);
/* critical region of code*/
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
exit(1);
pause();
..........
首先说明,这是个不理想的做法。如果信号发生在阻塞时,等解除阻塞时执行信号处理函数以后,pause返回,然后执行后面的程序。
pause函数:pause函数使调用进程挂起直至捕捉到一个信号,只有执行了一个信号处理函数并从其返回时,pause才返回。
如果在解除阻塞时刻和pause之间发生了信号,就丢失了。这样pause就一直挂在那等信号,这就是早期不可靠信号的机制的一个问题。
为了修正上面问题,需要在一个原子操作中先恢复信号屏蔽字,然后使进程休眠,这个功能就是由sigsuspend函数提供的。
int sigsuspend(const sigset_t *sigmask);
这个函数在一个不可中断的过程当中执行下面过程:
将进程的信号屏蔽字设置为sigmask指向的值,然后挂起,等待特定的信号,然后捕捉到一个信号并且从信号处理程序返回,则sigsuspend返回,
并且将给进程的信号屏蔽字设置为调用sigsuspend之前的值。
这个函数没有成功返回值,它总是返回-1,并置errno为EINTR。下面是几个sigsuspend应用实例:
几个实例等下期再写吧,今天下班。
1 保护临界区不被信号中断