歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux sigaction函數 sa_flags的值

Linux sigaction函數 sa_flags的值

日期:2017/2/28 16:18:21   编辑:Linux教程

開始對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,都對信號處理函數作用。

看運行結果:

www.linuxidc.com@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

Copyright © Linux教程網 All Rights Reserved