struct sigaction 和訊號處理函數的一些說明–1

來源:互聯網
上載者:User

轉自:http://hi.baidu.com/phps/blog/item/b064b7b71944cff630add1b4.html

 

linux 中訊號相關的一個結構體 struct sigaction 主要在sigaction訊號安裝和sigqueue訊號發送時會用到
該結構位於/usr/include/bits/sigaction.h
在裡面可以找到該結構的描述 {我現在實現的系統是as 4 核心版本 2.6.9-5.EL}
/* Structure describing the action to be taken when a signal arrives.     */
struct sigaction
     {
       /* Signal handler.     */
#ifdef __USE_POSIX199309
       union   
         {
       /* Used if SA_SIGINFO is not set.     */
       __sighandler_t sa_handler;
       /* Used if SA_SIGINFO is set.     */
       void (*sa_sigaction) (int, siginfo_t *, void *);
         }
       __sigaction_handler;



       # define sa_handler __sigaction_handler.sa_handler
       # define sa_sigaction      __sigaction_handler.sa_sigaction
#else
       __sighandler_t sa_handler;
#endif

 

       /* Additional set of signals to be blocked.     */
       __sigset_t sa_mask;

       /* Special flags.     */
       int sa_flags;

       /* Restore handler.     */
       void (*sa_restorer
) (void);
     };

在網上查了一些書料這個結構大概是這樣的
其中,sa_restorer,已淘汰,POSIX不支援它,不應再被使用。

1、聯合資料結構中的兩個元素_sa_handler以及*_sa_sigaction指定訊號關聯函數,即使用者指定的訊號處理函數。除了可以是使用者自訂的處理函數
外,還可以為SIG_DFL
(採用預設的處理方式),也可以為SIG_IGN
(忽略訊號)。
2、由_sa_handler指定的處理函數只有一個參數,即訊號值,所以訊號不能傳遞除訊號值之外的任何資訊

3、由_sa_sigaction是指定的訊號處理函數帶有三個參數,是為即時訊號而設的(當然同樣支援非即時訊號),它指定一個3參數訊號處理函數。第一個參數為訊號值,第三個參數沒有使用(posix沒有規範使用該參數的標準),第二個參數是指向siginfo_t結構的指標,結構中包含訊號攜帶的資料值,參數所指向的結構如下:
在/usr/include/bits/siginfo.h中是這樣定義的

typedef struct siginfo
{
     int si_signo;            /* Signal number.     */
     int si_errno;            /* If non-zero, an errno value associated with
                      this signal, as defined in <errno.h>.     */
     int si_code;             /* Signal code.     */

     union
     {
       int _pad[__SI_PAD_SIZE];

       /* kill().     */
       struct
       {
         __pid_t si_pid;          /* Sending process ID.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
       } _kill;

       /* POSIX.1b timers.     */
       struct
       {
         int si_tid;          /* Timer ID.     */
         int si_overrun;          /* Overrun count.     */
         sigval_t si_sigval;      /* Signal value.     */
       } _timer;

       /* POSIX.1b signals.     */
       struct
       {
         __pid_t si_pid;          /* Sending process ID.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
         sigval_t si_sigval;      /* Signal value.     */
       } _rt;

       /* SIGCHLD.     */
       struct
       {
         __pid_t si_pid;          /* Which child.     */
         __uid_t si_uid;          /* Real user ID of sending process.     */
         int si_status;           /* Exit value or signal.     */
         __clock_t si_utime;
         __clock_t si_stime;
       } _sigchld;

       /* SIGILL, SIGFPE, SIGSEGV, SIGBUS.     */
       struct
       {
         void *si_addr;           /* Faulting insn/memory ref.     */
       } _sigfault;

       /* SIGPOLL.     */
       struct
       {
         long int si_band;        /* Band event for SIGPOLL.     */
         int si_fd;
       } _sigpoll;
     } _sifields;
} siginfo_t;

是不是太複雜了,在網上有一個簡潔版我搬過來用一下

siginfo_t {
                     int         si_signo;     /* 訊號值,對所有訊號有意義*/
                     int         si_errno;     /* errno值,對所有訊號有意義*/
                     int         si_code;      /* 訊號產生的原因,對所有訊號有意義*/
union{      /* 聯合資料結構,不同成員適應不同訊號 */
//確保分配足夠大的儲存空間
int _pad[SI_PAD_SIZE];
//對SIGKILL有意義的結構
struct{
...
     }...
... ...
... ...
//對SIGILL, SIGFPE, SIGSEGV, SIGBUS有意義的結構
         struct{
...
     }...
... ...
     }
}







4、sa_mask指定在訊號處理常式執行過程中,哪些訊號應當被阻塞。預設情況下當前訊號本身被阻塞,防止訊號的嵌套發送,除非指定SA_NODEFER或者SA_NOMASK標誌位。

註:請注意sa_mask指定的訊號阻塞的前提條件,是在由sigaction()安裝訊號的處理函數執行過程中由sa_mask指定的訊號才被阻塞。

5、sa_flags中包含了許多標誌位,包括剛剛提到的SA_NODEFER及SA_NOMASK標誌位。另一個比較重要的標誌位是SA_SIGINFO,當設定了該標誌位時,表示訊號附帶的參數可以被傳遞到訊號處理函數中,因此,應該為sigaction結構中的sa_sigaction指定處理函數,而不應該為sa_handler指定訊號處理函數,否則,設定該標誌變得毫無意義。即使為sa_sigaction指定了訊號處理函數,如果不設定SA_SIGINFO,訊號處理函數同樣不能得到訊號傳遞過來的資料,在訊號處理函數中對這些資訊的訪問都將導致段錯誤(Segmentation fault)。

註:很多文獻在闡述該標誌位時都認為,如果設定了該標誌位,就必須定義三參數訊號處理函數。實際不是這樣的,驗證方法很簡單:自己實現一個單一參數訊號處理函數,並在程式中設定該標誌位,可以察看程式的運行結果。實際上,可以把該標誌位看成訊號是否傳遞參數的開關,如果設定該位,則傳遞參數;否則,不傳遞參數。

結構說的也差不多了,其實在我看到這些東西的時候給弄暈了好幾回,簡單的說幾句就是

如果要在某訊號產生時觸發某些動作我們就可以安裝訊號

signal 用於安裝不可靠訊號     linux現在是用sigaction實現的
sigaction 用於安裝可靠訊號 當然他也可以安裝不可靠訊號 並且可以附帶更多的資訊

signal安裝訊號時只需傳入2個參數 一個是訊號的值     一個是訊號發生時觸發的函數,該函數接受一個整數
sigaction 安裝時有3個參數 第一個參數是訊號的值,第二個是sigaction結構指標 這個結構說明了訊號發生時調用的函數和其它的一些資訊。第三個參數也是一個sigaction結構的指標oact,沒明白man page的說法,貌似和實際的運行有不符的地方。

If the argument oact is not a null pointer, the action previously associated  with the  signal is stored in the location pointed to by the argument oact. If the argument act is a null pointer, signal handling is unchanged; thus, the call can be used to enquire about the current  handling  of  a  given signal.

 

再說一下sigaction函數的第二個參數,其主要的成員是 sa_handler 指定的觸發函數只帶一個參數即訊號的值 這和signal調用沒什麼區別,sa_sigaction指定的觸發函數帶有3個參數 第一個參數是訊號的值,第二個參數是包函附加資訊的結構siginfo,第三個參數為空白 如果要傳遞附加資訊給觸發函數那麼必須將傳給sigaction的第二個參數sigaction結構的sa_flag設為SA_SIGINFO。

加一句,按照我對man的理解,其意思是當sa_flag設定了SA_SIGINFO的時候,就用sa_sigaction,沒設定的時候就用sa_handler。

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.