轉自: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。