开始对sa_flags有疑问,网上搜到都是这一个程序,就复制来说事:
代码:
	1 #include <stdio.h>
	2 #include <stdlib.h>
	3 #include <unistd.h>
	4 #include <signal.h>
	5
	6 void show_handler (int sig)
	7 {
	8         printf ("i got signal %d\n",sig);
	9         int i;
	10         for (i = 0 ; i < 5; i++)
	11         {
	12                 printf ("i= %d\n",i);
	13                 sleep(1);
	14         }
	15 }
	16
	17 int main(void)
	18 {
	19         int i = 0;
	20         struct sigaction act , oldact;
	21         act.sa_handler = show_handler;
	22         sigaddset (&act.sa_mask, SIGQUIT);  /*这个信号用户终端键入ctrl+\时产生,送至前台所有进程,不仅终止前台进程组,还产生core文件,这一程序的作用是把SIGQUIT加入信号>    集,对CTRL+\的屏蔽*/
	23         act.sa_flags =SA_RESETHAND|SA_NODEFER ; /*if sig    nal got ,set to SIG_DEF*/
	24         //act.sa_flags = 0; //(3)
	25         //sigprocmask(SIG_BLOCK, &act.sa_mask,NULL);
	26         //this can be used for add sigset mask
	27         sigaction(SIGINT,&act,&oldact);
	28         while (1)
	29         {
	30                 sleep (1);
	31                 printf ("sleeping %d\n", i);
	32                 i++;
	33         }
	34 }
	sigaction.sa_flags     控制内核对该信号的处理标记
	SA_NODEFER         一般情况下, 当信号处理函数运行时,内核将阻塞<该给定信号 -- SIGINT>。但是如果设置了SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号。 SA_NODEFER是这个标记的正式的POSIX名字(还有一个名字SA_NOMASK,为了软件的可移植性,一般不用这个名字)  
	SA_RESETHAND      当调用信号处理函数时,将信号的处理函数重置为缺省值。 SA_RESETHAND是这个标记的正式的POSIX名字(还有一个名字SA_ONESHOT,为了软件的可移植性,一般
上面是对sa_flags中常用的两个值的解释.]
疑问1:
act.sa_flags =SA_RESETHAND|SA_NODEFER ;
这一行程序中"|"按位或运算
那么sa_flags到底是什么样的值可以这样赋值,查看这个结构定义的根源:
/usr/include/bits/sigaction.h
	/* Bits in `sa_flags'.  */
	54 #define SA_NOCLDSTOP  1          /* Don't send SIGCHLD when children stop.  */
	55 #define SA_NOCLDWAIT  2          /* Don't create zombie on child death.  */
	56 #define SA_SIGINFO    4          /* Invoke signal-catching function with
	57                                     three arguments instead of one.  */
	58 #if defined __USE_UNIX98 || defined __USE_MISC
	59 # define SA_ONSTACK   0x08000000 /* Use signal stack by using `sa_restorer'. */
	60 #endif
	61 #if defined __USE_UNIX98 || defined __USE_MISC || defined __USE_XOPEN2K8
	62 # define SA_RESTART   0x10000000 /* Restart syscall on signal return.  */
	63 # define SA_NODEFER   0x40000000 /* Don't automatically block the signal when
	64                                     its handler is being executed.  */
	65 # define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler.  */
	66 #endif
	67 #ifdef __USE_MISC
	68 # define SA_INTERRUPT 0x20000000 /* Historical no-op.  */
	可以看到sa_flags的值可以是上面的值在值的定义中看到每个宏都有一个数字相对应:这样这句程序就不难理解啦,也就是说它同时定义啦 SA_NODEFER和 SA_RESETHAND,都对信号处理函数作用。
看运行结果:
	linux@Ubuntu:~/apuestudy/10/3$ ./sig3
	sleeping 0
	sleeping 1
	^Ci got signal 2
	i= 0
	i= 1
	^C
	这里先ctrl+c进入信号处理函数,然后ctrl+c终止程序,应为有sa_resethan是在信号处理函数中ctrl+c变为默认,这样就终止
	sleeping 0
	sleeping 1
	^\退出
	这个简单,就没进信号处理函数,
	sleeping 0
	^Ci got signal 2
	i= 0
	i= 1
	^\i= 2
	^\i= 3
	i= 4
	退出
	这个进入信号处理函数,键入ctrl+\,由于 sigaddset (&act.sa_mask, SIGQUIT)键所以对ctrl+\屏蔽,但回到主进程中依然会处理该信号,故退出,
好啦:现在把sa_flags改为sa_nodefer
	i got signal 2
	i= 0
	i= 1
	i= 2
	i= 3
	^Ci got signal 2
	i= 0
	i= 1
	^Ci got signal 2
	i= 0
	i= 1
	^\i= 2
	i= 3
	i= 4
	i= 2
	i= 3
	i= 4
	i= 4
	退出
	呵呵,sigaddset (&act.sa_mask, SIGQUIT);信号处理函数函数依然屏蔽,到主函数停止,
但是可以在信号处理函数中多次ctrl+c而不会推出,因为没有 SA_RESETHAND 所以不会恢复默认处理,还有个有趣的现象是i的输出顺序,这个没有信号队列的处理机制,小弟水平有限。
再看看只有 SA_RESETHAND
	sleeping 0
	^Ci got signal 2
	i= 0
	i= 1
	^Ci= 2
	i= 3
	^\i= 4
	这里有可能有人问, SA_RESETHAND 恢复默认,为什么没有停止,应为没有设置sa_nodefer
所以处理函数是对ctrl+c是阻塞的,只有到主函数中才有作用,
还有一个结果
	sleeping 0
	^Ci got signal 2
	i= 0
	i= 1
	^\i= 2
	^Ci= 3
	i= 4
	这个和上面的一样,但是在信号处理函数中,我把ctrl+c与ctrl+\的执行顺序便啦,如果ctrl+\作用,则在最后有“退出”两个子,可是这两个顺序都没有,可见不管是那个执行,都是ctrl+c作用结束啦程序,这个可能与信号与信号优先级有关??水平有限,待高手
小弟刚自学linux编程,以上只是根据试验结果自己理解,如有错误,恳请指教,
Q:915311043
今天又看程序发现以前有不完全的理解:
如果我们只用SA—NODEFER,这样会发现只要ctrl+c键入一次,就会运行一次handler(信号处理函数);
而你对信号作用的设置,只是对信号处理函数有作用,在主函数中ctrl+\仍然会终止程序,但是为什么键入ctrl+c不会终止,应为sigaction函数捕捉的是sigint(ctrl+c产生的信号),所以会再次产生handler。

