Linux提供了一個更見健壯的訊號介面:sigaction。
#include<signal.h>
int sigaction( int sig, const struct sigaction *act , struct sigaction *ocat);
sigaction結構定義在檔案signal.h中,它的作用是定義在接收到參數sig指定的訊號後應該採用的行動。該結構至少應該包含一下
以下幾個成員 。
void (*) (int ) sa_handler /*function, SIG_DFL or SIG_IGN*/
sigset_t sa_mask /*signals to block in sa_handler*/
int sa_flags /* signal action modifiers*/
sigaction函數會在成功時返回0,失敗時返回0.
在參數cat指向的sigaction結構中,sa_handler是一個函數指標,它指向訊號sig時將被調用的訊號處理函數。
sa_mask成員指定了一個訊號集,在調用Sa_handler所指向的訊號處理函數之前,該訊號集將被加入到進程的訊號屏蔽字中。
#include <signal.h>#include <stdio.h>#include <unistd.h>void ouch(int sig){ printf("OUCH! - I got signal %d\n", sig);}int main(){ struct sigaction act; act.sa_handler = ouch; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, 0); while(1) { printf("Hello World!\n"); sleep(1); }}
訊號集
標頭檔signal.h定義了類型sigset_t和用來處理訊號集的函數。sigaction和其他函數將用這些訊號集來修改進程在接收到訊號時的行為。
#include<signal.h>int sigaddset(sigset_t *set, int signo);int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigdelset(sigset_t *set , int signo);
sigempty將訊號集初始化為空白。sigfillset將訊號處理化為包含所以已定義的訊號。sigaddset和sigdelset從訊號集中增加或刪除給定的訊號
(signo)。它們在成功時返回0,失敗時返回-1並設定errno。
函數sigismember判斷一個給定的訊號是否是一個訊號集的成員。如果是就返回1,如果不是,它就返回0.給定的訊號無效,它就返回-1並
設定errno為EINVAL。
#include<signal.h>
int sigismember(sigset_t *set , int signo);
進程的訊號屏蔽字的設定或檢查工作由函數sigprocmask來完成。訊號屏蔽字是指當前被阻塞的一組訊號,他們不能被當前進程接收到
#include<signal.h>
int sigprocmask(int how , const sigset_t *set , sigset_t *oset);
sigprocmask函數可以根據參數how指定的方法修改進程的訊號屏蔽字。新的訊號屏蔽字由參數set指定。
參數how的取值可以是表11-6中的一個。
SIG_BLOCK 把參數set中的訊號添加到訊號屏蔽字中。
SIG_SETMASK 把訊號屏蔽字設定為參數set中的訊號。
SET_UNBLOCK 從訊號屏蔽字中刪除參數set中的訊號。
如果一個訊號被進程阻塞,它就不會傳遞給進程。但它停留在待處理狀態,程式可以通過調用函數sigpending來查看它阻塞的訊號中
有哪些正停留在待處理狀態。
#include<signal.h>
int sigpending(sigset_t *set);
進程可以通過調用sigsuspend函數掛起自己的執行,知道訊號集中的一個訊號到達為止。
#include<signal.h>
int sigsuspend(const sigset_t *sigmask);
這個函數將自己的進程屏蔽字替換為由參數sigmask給出的訊號集,然後掛起程式的執行。
1.sigaction標誌
用在sigaction函數裡的sigaction結構中的sa_flags
SA_NOCLDSTOP: 如果SA_NOCLDSTOP位被置位並且目標訊號是SIGCHLD,除非子進程退出,而在子進程停止(stop)時父進程將不會收到通知。
SA_NOCLDWAIT: SA_NOCLDWAIT標誌會阻止子進程成為殭屍進程。在目標訊號是SIGCHLD的時候使用。如果進程設定了這個標誌,接著調用某個wait系統調用,進程將被阻塞直到子進程全部終止,最後返回-1(譯註:此處在APUE2ed中的解釋是返回1),設定errno全域變數為ECHILD。
SA_ONSTACK: 一些時候需要在特定的堆棧上進行訊號的處理。sigaction系統調用提供了這個方式。如果該位被置位,那麼訊號將會被交付到指定的堆棧上。
SA_NODEFER: 如果SA_NODEFER位被置位,那麼當前訊號正被處理時,系統不會屏蔽該訊號以後的交付。