linux系統編程之訊號(六):訊號發送函數sigqueue和訊號安裝函數sigaction

來源:互聯網
上載者:User

一,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結構定義如下:

 (*_sa_sigaction)(, siginfo *,  * (*sa_restorer)(

其中,sa_restorer,已淘汰,POSIX不支援它,不應再被使用。

1、聯合資料結構中的兩個元素_sa_handler以及*_sa_sigaction指定訊號關聯函數,即使用者指定的訊號處理函數。除了可以是使用者自訂的處理函數外,還可以為SIG_DFL(採用預設的處理方式),也可以為SIG_IGN(忽略訊號)。

2、由_sa_handler指定的處理函數只有一個參數,即訊號值,所以訊號不能傳遞除訊號值之外的任何資訊;由_sa_sigaction是指定的訊號處理函數帶有三個參數,是為即時訊號而設的(當然同樣支援非即時訊號),它指定一個3參數訊號處理函數。第一個參數為訊號值,第三個參數沒有使用(posix沒有規範使用該參數的標準),第二個參數是指向siginfo_t結構的指標,結構中包含訊號攜帶的資料值,參數所指向的結構如下:

typedef  si_signo; si_errno; si_code;pid_t si_pid;pid_t si_uid; si_status;clock_t si_utime;clock_t si_stime; **

 

siginfo_t結構中的聯合資料成員確保該結構適應所有的訊號,比如對於即時訊號來說,則實際採用下面的結構形式:

typedef 

結構的第四個域同樣為一個聯合資料結構:

 *

採用聯合資料結構,說明siginfo_t結構中的si_value要麼持有一個4位元組的整數值,要麼持有一個指標,這就構成了與訊號相關的資料。在訊號的處理函數中,包含這樣的訊號相關資料指標,但沒有規定具體如何對這些資料進行操作,操作方法應該由程式開發人員根據具體任務事先約定。

sigval結構體:系統調用sigqueue發送訊號時,sigqueue的第三個參數就是sigval聯合資料結構,當調用sigqueue時,該資料結構中的資料就將拷貝到訊號處理函數的第二個參數中。這樣,在發送訊號同時,就可以讓訊號傳遞一些附加資訊。訊號可以傳遞資訊對程式開發是非常有意義的。

siginfo_t.si_value與sigqueue(pid_t pid, int sig, const union sigval val)第三個參數關聯即:

所以通過siginfo_t.si_value可以獲得sigqueue(pid_t pid, int sig, const union sigval val)第三個參數傳遞過來的資料。

如:siginfo_t.si_value.sival_int或siginfo_t.si_value.

訊號參數的傳遞過程可圖示如下:

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

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

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

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

二,sigqueue()

之前學過kill,raise,alarm,abort等功能稍簡單的訊號發送函數,現在我們學習一種新的功能比較強大的訊號發送函數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指定的資訊會拷貝到對應sig 註冊的3參數訊號處理函數的siginfo_t結構中,這樣訊號處理函數就可以處理這些資訊了。由於sigqueue系統調用支援發送帶參數訊號,所以比kill()系統調用的功能要靈活和強大得多。

三,sigqueue與sigaction應用執行個體

執行個體一:利用sigaction安裝SIGINT訊號

#include <unistd.h><sys/stat.h><sys/wait.h><sys/types.h><fcntl.h><stdlib.h><stdio.h><errno.h><.h><signal.h> ERR_EXIT(m) \    ( handler( main( argc,  *=&=      (sigaction(SIGINT, &act, NULL) <   handler(

結果:

<sys/stat.h><sys/wait.h><sys/types.h><fcntl.h><stdlib.h><stdio.h><errno.h><.h><signal.h> ERR_EXIT(m) \ ( handler( main( argc, * =&= (sigaction(sig, &act, &oldact) < handler(

結果:

<sys/stat.h><sys/wait.h><sys/types.h><fcntl.h><stdlib.h><stdio.h><errno.h><.h><signal.h> ERR_EXIT(m) \ ( handler( main( argc, *=&&= (sigaction(SIGINT, &act, NULL) < =&= (sigaction(SIGQUIT, &act2, NULL) < handler((sig == (sig ==

結果:

<unistd.h><signal.h><stdlib.h> sighandler( signo, siginfo_t *info, * main(=&= SA_SIGINFO; (sigaction(SIGINT,&act,NULL) == -= (sigqueue(getpid(),SIGINT,mysigval) == - sighandler( signo, siginfo_t *info, * printf(,info->,info->

結果:

<unistd.h><signal.h><stdlib.h> sighandler( signo, siginfo_t *info, * main(=&= SA_SIGINFO; (sigaction(SIGINT,&act,NULL) == - sighandler( signo, siginfo_t *info, * printf(,info->,info->

發送端:

#include <stdio.h><unistd.h><signal.h><stdlib.h> main( argc,  **(argc != ,argv[= atoi(argv[= (sigqueue(pid,SIGINT,mysigval) == - 

結果:

由圖可知接收成功

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.