今天只看SIGQUEUE函數:聲明:其中有部分
http://www.bccn.net/Article/kfyy/vc/jszl/200708/5849.html(編程中國)的摘抄:
3、sigqueue()
#include <sys/types.h>
#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval val)
調用成功返回 0;否則,返回 -1。
sigqueue()是比較新的發送訊號系統調用,主要是針對即時訊號提出的(當然也支援前32種),支援訊號帶有參數,與函數sigaction()配合使用。
sigqueue的第一個參數是指定接收訊號的進程ID,第二個參數確定即將發送的訊號,第三個參數是一個聯合資料結構union sigval,指定了訊號傳遞的參數,即通常所說的4位元組值。
typedef union sigval { int sival_int; void *sival_ptr; }sigval_t;
|
sigqueue()比kill()傳遞了更多的附加資訊,但sigqueue()只能向一個進程發送訊號,而不能發送訊號給一個進程組。如果
signo=0,將會執行錯誤檢查,但實際上不發送任何訊號,0值訊號可用於檢查pid的有效性以及當前進程是否有許可權向目標進程發送訊號。
在調用sigqueue時,sigval_t指定的資訊會拷貝到3參數訊號處理函數(3參數訊號處理函數指的是訊號處理函數由sigaction安
裝,並設定了sa_sigaction指標,稍後將闡述)的siginfo_t結構中,這樣訊號處理函數就可以處理這些資訊了。由於sigqueue系統
調用支援發送帶參數訊號,所以比kill()系統調用的功能要靈活和強大得多。
註:sigqueue()發送非即時訊號時,第三個參數包含的資訊仍然能夠傳遞給訊號處理函數; sigqueue()發送非即時訊號時,仍然不支援排隊,即在訊號處理函數執行過程中到來的所有相同訊號,都被合并為一個訊號。
***************************************************************************************************************************
根據以上對SIGQUEUE函數的講解,
在調用sigqueue時,sigval_t指定的資訊會拷貝到3參數訊號處理函數(3參數訊號處理函數指的是訊號處理函數由sigaction安裝,並
設定了sa_sigaction指標,稍後將闡述)的siginfo_t結構中,這樣訊號處理函數就可以處理這些資訊了。由於sigqueue系統調用支
持發送帶參數訊號
這一部分較難理解:
SIGQUEUE函數的第三個參數是拷貝到SIGQUEUE函數中的,這裡有一個3參數SIGQUEUE函數,以下是關於SIGACTION函數此方面的詳解:
***********************************************SIGACTION*************************************************************
sigaction()
#include <signal.h>
int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact));
sigaction函數用於改變進程接收到特定訊號後的行為。該函數的第一個參數為訊號的值,可以為除SIGKILL及SIGSTOP外的任何一個
特定有效訊號(為這兩個訊號定義自己的處理函數,將導致訊號安裝錯誤)。第二個參數是指向結構sigaction的一個執行個體的指標,在結構
sigaction的執行個體中,指定了對特定訊號的處理,可以為空白,進程會以預設方式對訊號處理;第三個參數oldact指向的對象用來儲存原來對相應訊號
的處理,可指定oldact為NULL。如果把第二、第三個參數都設為NULL,那麼該函數可用於檢查訊號的有效性。
第二個參數最為重要,其中包含了對指定訊號的處理、訊號所傳遞的資訊、訊號處理函數執行過程中應屏蔽掉
sigaction的結構形態如下:
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}
參數:
在一些體繫上,sa_handler和sa_sigaction共用一個聯合體(union),所以不要同時指定兩個欄位的值。
sa_restorer欄位已淘汰,不應該再被使用。
sa_handler欄位指定與signum訊號關聯的行為,可能是SIG_DFL預設行為,SIG_IGN忽略接送到的訊號,或者一個訊號處理函數指標。這個函數以一個訊號編碼作為它的唯一參數
。
如果sa_flags中存在SA_SIGINFO標誌,那麼sa_sigaction將作為signum訊號的處理函數。這個函數的第一參數是訊號編碼,第二參數是siginfo_t結構的指標,第三參數是ucontext_t結構指標(造型為void *)。
sa_mask指定訊號處理函數執行的過程中應被阻塞的訊號。另外,除了SA_NODEFER標誌被指定外,觸發訊號處理函數執行的那個訊號也會被阻塞。
sa_flags指定一系列用於修改訊號處理過程行為的標誌,由下面的0個或多個標誌通過or運算組合而成:
SA_NOCLDSTOP //此標誌為on時,假如signum的值是SIGCHLD,則在子進程停止或恢複執行時不會傳訊號給調用本系統調用的進程。
SA_NOCLDWAIT //此標誌為on時,當調用此系統調用的進程之子進程終止時,系統不會建立zombie進程。
SA_RESETHAND //此標誌為on時,訊號處理函數接收到訊號後,會先將對訊號處理的方式設為預設方式,而且當函數處理該訊號時,後來發生的訊號將不會被阻塞。
SA_ONSTACK //如果利用sigaltstack()建立訊號專用堆棧,則此標誌會把所有訊號送往該堆棧。
SA_RESTART //此標誌為on時,核心會自動重啟訊號中斷的系統調用,否則返回EINTR錯誤值。
SA_NODEFER //當此標誌為on時,在訊號處理函數處置訊號的時段中,核心程式不會把這個間隙中產生的訊號阻塞。
SA_SIGINFO //此標誌為on時,指定訊號處理函數需要三個參數,所以應使用sa_sigaction替代sa_handler。
看看標頭檔:
#define SA_SIGINFO 4 /* Invoke signal-catching function with
57 three arguments instead of one. */
這是標頭檔中對SA-SIGINFO的描述****************************************************************
好啦,到目前我們捋捋思路:
函數sigaction()的第二個參數指向一個struct sigaction結構的指標,這個結構中有兩個函數指標
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
他們都可以作為訊號處理函數,使用那一個就要看SA-FLAGS是否標誌位SA-SIGINFO,標誌啦,就用sa_sigaction指標指向的函數,沒有標誌,就使用sa_handler指向的函數。
由_sa_handler指定的處理函數只有一個參數,即訊號值,所以訊號不能傳遞除訊號值之外的任何資訊;由_sa_sigaction是指定的訊號處
理函數帶有三個參數,是為即時訊號而設的(當然同樣支援非即時訊號),它指定一個3參數訊號處理函數。第一個參數為訊號值,第三個參數沒有使用
(posix沒有規範使用該參數的標準),第二個參數是指向siginfo_t結構的指標,結構中包含訊號攜帶的資料值,參數所指向的結構如下:
sa_sigaction第二個參數siginfo_t結構的原型如下:
siginfo_t {
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal */
void * si_ptr; /* POSIX.1b signal */
void * si_addr; /* Memory location which caused fault */
int si_band; /* Band event */
int si_fd; /* File descriptor */
}
看見加黑的結構體沒有,這個才是我們今天堯討論的
他的定義和sigval這個結構定義在一個標頭檔中<siginfo.h>
下面是sigval的結構體定義:
/* Type for data associated with a signal. */
33 typedef union sigval
34 {
35 int sival_int;
36 void *sival_ptr;
37 } sigval_t;
採用聯合資料結構,說明siginfo_t結構中的si_value要麼持有一個4位元組的整數值,要麼持有一個指標,這就構成了與訊號相關的資料。在訊號
的處理函數中,包含這樣的訊號相關資料指標,但沒有規定具體如何對這些資料進行操作,操作方法應該由程式開發人員根據具體任務事先約定。
************************************************SIGACTION***************************************************************
現在回到SIGQUEUE函數:
在調用sigqueue時,sigval_t指定的資訊會拷貝到3參數訊號處理函數(3參數訊號處理函數指的是訊號處理函數由sigaction安裝,並
設定了sa_sigaction指標)的siginfo_t結構中,這樣訊號處理函數就可以處理這些資訊了。由於sigqueue系統調用支
持發送帶參數訊號,所以比kill()系統調用的功能要靈活和強大得多。
現在就好理解這段話啦!!!