天天看點

sigaction 和 sigqueue 函數

sigaction 函數的功能是檢查或修改與指定信号相關聯的處理動作。

其中,參數 signo 是要檢測或修改其具體動作的信号編号;若 act 指針非空,則指定要修改的動作;若 oact 指針非空,則系統用其傳回該信号的上一個動作。一旦對給定的信号設定了一個動作,那麼在調用 sigaction 顯示地改變它之前,該設定就一直有效。

在 sigaction 結構中,當更改信号動作時,如果 sa_handler 字段包含一個信号捕捉函數的位址(不是 SIG_IGN 或 SIG_DFL),則在調用該捕捉函數前,sa_mask 字段說明的信号集将被加到程序的信号屏蔽字中,僅當從捕捉函數傳回後再恢複程序的信号屏蔽字。這樣,在調用信号處理程式時就能阻塞某些信号,此時作業系統建立的新信号屏蔽字還包括正被遞送的信号,是以保證了在處理一個給定的信号時,如果這種信号再次發生,則它會被阻塞到對前一個信号的處理結束為止。sa_flags 字段則指定了對信号進行處理的各個選項,它們的意義如下表所示。

[img]http://dl2.iteye.com/upload/attachment/0127/2473/49bb2ef2-347d-386a-a4b1-ecb449fcd36f.png[/img]

sa_sigaction 字段是一個替代的信号處理程式,當 sa_flags 指定了 SA_SIGINFO 标志時就會使用該信号處理程式。當實作支援實時信号擴充時,用 SA_SIGINFO 标志建立的信号處理程式将造成信号可靠地排隊。一些保留信号可由實時應用使用。如果信号由 sigqueue 函數産生,則 siginfo 結構能包含應用特有的資料。

siginfo 結構包含了信号産生原因的有關資訊,符合 POSIX.1 的所有實作必須至少包括 si_signo 和 si_code 成員。應用程式在遞送信号時,在 si_value.sival_int 中傳遞一個整型數或者在 si_value.sival_ptr 中傳遞一個指針值。下表顯示了對各種信号的 si_code 值(這些信号是由 Single UNIX Specification 定義的,實作也可定義附加的代碼值)。

[img]http://dl2.iteye.com/upload/attachment/0127/2489/2517fd4a-94d6-3684-bdbd-d5ccafd1b65c.png[/img]

若信号是 SIGCHLD,則将設定 si_pid、si_status 和 si_uid 字段。若信号是 SIGBUS、SIGILL、SIGFPE 或 SIGSEGV,則 si_addr 包含造成故障的根源位址,不過可能并不準确。si_errno 包含錯誤編号,它對應造成信号産生的條件,并由實作定義。

信号處理程式的 context 參數可被強制類型轉換為 ucontext_t 結構類型,該結構辨別信号傳遞時程序的上下文。uc_stack 字段描述了目前上下文使用的棧。

大部分 UNIX 系統不對信号排隊,但在 POSIX.1 的實時擴充中,有些系統開始增加對信号排隊的支援。通常一個信号帶有一個位資訊:信号本身。除了對該信号排隊以外,這些擴充允許應用程式在遞交信号時傳遞更多的資訊,這些資訊嵌入在 siginfo 結構中。除了系統提供的資訊,應用程式還可以向信号處理程式傳遞整數或者指向包含更多資訊的緩沖區指針。

使用排隊信号必須做以下幾個操作。

(1)使用 sigaction 函數安裝信号處理程式時指定 SA_SIGINFO 标志。如果沒有給出該标志,信号會延遲,但信号是否進入隊列要取決于具體實作。

(2)在 sigaction 結構的 sa_sigaction 成員(而不是通常的 sa_handler)中提供信号處理程式。實作可能允許使用者使用 sa_handler 字段,但不能擷取 sigqueue 函數發送出來的額外資訊。

(3)使用 sigqueue 函數發送信号。

信号不能被無限排隊,到達 SIGQUEUE_MAX 限制後 sigqueue 就會失敗,并将 errno 設為 EAGAIN。

下面是用 sigaction 函數實作的 signal 函數(可以通過指定 SA_RESETHAND 和 SA_NODEFER 選項以實作老的不可靠信号語義的 signal 函數)。

這裡,對除 SIGALRM 以外的所有信号都有意嘗試設定 SA_RESTART 标志,于是被這些信号中斷的系統調用都能自動重新開機動。不希望重新開機動 SIGALRM 中斷的系統調用的原因是:希望對慢速 I/O 操作可以使用 alarm 函數設定時間限制。另外,某些早期系統(如 SunOS)定義了 SA_INTERRUPT 标志,這些系統的預設方式是重新開機動被中斷的系統調用,而指定此标志就可以使其不再重新開機動。XSI 擴充規定,除非說明了 SA_RESTART 标志,否則 sigaction 函數不再重新開機動被中斷的系統調用。