一、signal 是不可靠的:
在Ubuntu10.04,Kernel 2.6.23上,其设置的信号函数仅仅触发一次,触发完之后恢复为默认动作,但是sigaction函数设置之后一直有效;
如下代码(摘自UNIX环境高级编程)当使用signal时,仅仅触发一次sig_int,再次发送中断信号执行默认操作:程序被终止;
但是用sigaction设置,一直会触发sig_int函数;
#include "../apue.h"
volatile sig_atomic_t quitflag;
static void sig_int(int signo)
{
if(signo == SIGINT)
printf("\n interrupt\n");
else if(signo == SIGQUIT)
quitflag = 1;
}
int main(void)
{
sigset_t newmask,oldmask,zeromask;
#if 0
if(signal(SIGINT, sig_int) == SIG_ERR)
err_sys(" signal(SIGINT) error");
if(signal(SIGQUIT, sig_int) == SIG_ERR)
err_sys("signal(SIGQUIT) error");
#endif
struct sigaction act;
act.sa_handler = sig_int;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if(sigaction(SIGINT, &act, NULL) < 0)
err_sys("sigaction SIGINT error");
if(sigaction(SIGQUIT, &act, NULL) < 0)
err_sys("sigaction SIGINT error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
// Block SIGQUIT and save current signal mask
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
while(quitflag==0)
{
sigsuspend(&zeromask);
}
quitflag = 0;
// reset signal mask
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("failed to set mask");
exit(0);
}
二、sigsuspend(const sigset_t *sigmask)的理解:
该函数将信号屏蔽字设置为由sigmask指向的值,//就是说新的信号屏蔽字为sigmask,如果你之前调用sigprocmask设置了信号屏蔽字,那么这个设置会失效,当sigsuspend返回时,才能恢复为sigprocmask设置的值;
在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。
如果捕捉到一个信号且从处理程序返回,则sigsuspend返回,并且将该进程的信号屏蔽字设置为调用sigsuspend之前的值;//此时sigsuspend设置的sigmask失效,之前的屏蔽字恢复;
原文:http://blog.csdn.net/wei_gw2012/article/details/78389286