出处:http://hi.baidu.com/xu_zhisheng/blog/item/82cbdfd7ab12872607088bdc.html#0
转载+原创
加上自己的总结与程序的调试并验证!
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void show_handler(int sig)
{
printf("I got signal %d\n", sig);
int i;
for(i = 0; i < 10; i++)
{
printf("i = %d\n", i);
sleep(1); /*for inputting interupt signal*/
}
}
int main(void)
{
int i = 0;
struct sigaction act, oldact;
act.sa_handler = show_handler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGQUIT); //将SIGQUIT(Ctrl+\)信号加入信号集
// sigaddset(&act.sa_mask, SIGINT); //将SIGINT(Ctrl+C)信号加入信号集
/***(2)if signal got,then set to the signal to SIG_DFL(the default signal)
and the signal occur immediately.***/
act.sa_flags = SA_RESETHAND | SA_NODEFER;
//act.sa_flags = 0; //(3)
/*This can be used for add sigset mask,and then block the signal SIGOUIT or SIGINT*/
//sigprocmask(SIG_BLOCK,&act.sa_mask,NULL);
sigaction(SIGINT, &act, &oldact);
while(1) {
sleep(1);
printf("sleeping %d\n", i);
i++;
}
}
(一)在act.sa_flags = SA_RESETHAND | SA_NODEFER的情况下
#gcc -g -o text_sigaction text_sigaction.c
执行结果如下:
/********************(1)*********************/
#./text_sigaction
sleeping 0
sleeping 1
sleeping 2
I got signal 2 /***Ctrl+C***/
i = 0
i = 1
i = 2 /**Ctrl+C****/ /****因为 act.sa_flags = SA_RESETHAND | SA_NODEFER;
一句,表明:Ctrl+C 的信号恢复到系统的默认状态,
且执行该信号不延迟,不再进入信号处理中执行了!***/<---------见注释(1)
#
/**********************(2)********************/
#./text_sigaction
sleeping 0
sleeping 1
sleeping 2
I got signal 2 /**Ctrl+C**/ 该信号恢复到默认状态,且不延迟。
i = 0
i = 1
i = 2
i = 3 /***Ctrl+\**/ SIGQUIT信号阻塞!<--------------------见注释(2)
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
退出
#
/*************(3)*******************/
#./text_sigaction
sleeping 0
sleeping 1
sleeping 2
sleeping 3
sleeping 4 /***Ctrl+\**/ 信号直接退出。
退出
#
/*******************(4)***************/
#./text_sigaction
sleeping 0
sleeping 1
sleeping 2
I got signal 2 /***Ctrl+C***/ /***第一次进入信号处理函数,且该信号变为默认,且不延迟*****/
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
sleeping 3
sleeping 4
sleeping 5 /****Ctrl+C***/ /***第二次不进入信号处理函数,而是执行系统的该信号的默认情况***/
#
注释(1)
第二次"CTRL+C",由于act.sa_flags = SA_RESETHAND | SA_NODEFER 。SA_RESETHAND: 信号发给进程后,把信号处理器复位为缺省值SIG_DFL,所以第二次按Ctrl+C时, 信号处理器已经复位为SIG_DFL,对SIGINT来说,缺省动作就是终止进程。
注释(2)
如果在信号SIGINT(Ctrl + c)的信号处理函数show_handler执行过程中,本进程收到信号SIGQUIT(Crt+\),将阻塞该信号,直到show_handler执行结束才会处理信号SIGQUIT。
(二)在act.sa_flags = SA_RESETHAND | SA_NODEFER;------->act.sa_flags =SA_NODEFER;的情况下;
#./text_sigaction1
sleeping 0
sleeping 1
sleeping 2
sleeping 3
I got signal 2 /**Ctrl+C***/
i = 0
i = 1
i = 2
I got signal 2 /**Ctrl+C**/
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5 <---------- 可见是将Ctrl+C的信号压入队列!!
i = 3
i = 4
i = 5
sleeping 4
sleeping 5 /**Ctrl+\**/
退出
#
sigaction.sa_flags 控制内核对该信号的处理标记
SA_NODEFER 一般情况下, 当信号处理函数运行时,内核将阻塞<该给定信号 -- SIGINT>。但是如果设置了SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号。 且将信号的调用次数压入队列!SA_NODEFER是这个标记的正式的POSIX名字(还有一个名字SA_NOMASK,为了软件的可移植性,一般不用这个名字)
SA_RESETHAND 当调用信号处理函数时,将信号的处理函数重置为缺省值。 SA_RESETHAND是这个标记的正式的POSIX名字(还有一个名字SA_ONESHOT,为了软件的可移植性,一般不用这个名字)
SA_SIGINFO 信号处理函数是带有三个参数的sa_sigaction
*** 如果不需要重置该给定信号的处理函数为缺省值;并且不需要阻塞该给定信号(无须设置sa_flags标志),那么必须将sa_flags清零(?????这里有点理解不了怎么个清零法),否则运行将会产生段错误。但是sa_flags清零后可能会造成信号丢失!
注: 阻塞的意思是延迟相应信号