sigaction() - Unix 和 Linux 系統呼叫 - 技術教學
Tutorials Point


  Unix 初學者指南
  Unix Shell 程式設計
  高階 Unix
  Unix 有用參考
  Unix 有用資源
  精選閱讀

版權所有 © 2014 tutorialspoint



  首頁     參考     討論論壇     關於 TP  

sigaction() - Unix 和 Linux 系統呼叫


previous next AddThis Social Bookmark Button

廣告

名稱

sigaction - 檢查和更改訊號操作

語法

#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

描述

sigaction() 系統呼叫用於更改程序在收到特定訊號時採取的操作。

signum 指定訊號,可以是任何有效的訊號,除了 SIGKILLSIGSTOP

如果 act 非空,則從 act 安裝訊號 signum 的新操作。如果 oldact 非空,則將先前操作儲存到 oldact 中。

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_handlersa_sigaction 賦值。

sa_restorer 元素已過時,不應使用。POSIX 未指定 sa_restorer 元素。

sa_handler 指定要與 signum 關聯的操作,可以是 SIG_DFL(預設操作),SIG_IGN(忽略此訊號),或者是指向訊號處理函式的指標。此函式接收訊號編號作為其唯一引數。

如果在 sa_flags 中指定了 SA_SIGINFO,則 sa_sigaction(而不是 sa_handler)指定 signum 的訊號處理函式。此函式接收訊號編號作為其第一個引數,指向 siginfo_t 的指標作為其第二個引數,以及指向 ucontext_t(強制轉換為 void *)的指標作為其第三個引數。

sa_mask 給出一個訊號掩碼,這些訊號應在執行訊號處理程式期間被阻塞。此外,觸發處理程式的訊號將被阻塞,除非使用了 SA_NODEFER 標誌。

sa_flags 指定一組標誌,這些標誌修改訊號處理過程的行為。它由以下零個或多個標誌的按位或組成

標籤描述
SA_NOCLDSTOP
 如果 signumSIGCHLD,則在子程序停止(即,當它們收到 SIGSTOPSIGTSTPSIGTTINSIGTTOU 中的一個)或恢復(即,它們收到 SIGCONT)時,不接收通知(參見 wait(2))。
SA_NOCLDWAIT
 (Linux 2.6 及更高版本)如果 signumSIGCHLD,則當子程序終止時,不要將其轉換為殭屍程序。另請參見 waitpid(2) 。
SA_RESETHAND
 一旦呼叫訊號處理程式,就將訊號操作恢復為預設狀態。SA_ONESHOT 是此標誌的已過時非標準同義詞。
SA_ONSTACK
 sigaltstack(2) 提供的備用訊號棧上呼叫訊號處理程式。如果備用棧不可用,則將使用預設棧。
SA_RESTART
 透過使某些系統呼叫能夠跨訊號重新啟動,提供與 BSD 訊號語義相容的行為。
SA_NODEFER
 不要阻止從其自己的訊號處理程式中接收訊號。SA_NOMASK 是此標誌的已過時非標準同義詞。
SA_SIGINFO
 訊號處理程式接受 3 個引數,而不是一個。在這種情況下,應設定 sa_sigaction 而不是 sa_handler。(sa_sigaction 欄位是在 Linux 2.1.86 中新增的。)

sa_sigactionsiginfo_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 */
}

si_signosi_errnosi_code 對所有訊號都已定義。(si_signo 在 Linux 上未使用。)結構的其餘部分可能是一個聯合體,因此只能讀取對給定訊號有意義的欄位。POSIX.1b 訊號和 SIGCHLD 將填充 si_pidsi_uidSIGCHLD 還填充 si_statussi_utimesi_stimesi_intsi_ptr 由 POSIX.1b 訊號的發件人指定。SIGILLSIGFPESIGSEGVSIGBUSsi_addr 填充為錯誤地址。SIGPOLL 填充 si_bandsi_fd

si_code 指示傳送此訊號的原因。它是一個值,而不是一個位掩碼。任何訊號可能出現的值在此表中列出

si_code
訊號來源
SI_USERkill()、sigsend() 或 raise()
SI_KERNEL核心
SI_QUEUEsigqueue()
SI_TIMERPOSIX 定時器過期
SI_MESGQPOSIX 訊息佇列狀態更改(自 Linux 2.6.6 起)
SI_ASYNCIOAIO 完成
SI_SIGIO排隊的 SIGIO
SI_TKILLtkill() 或 tgkill()(自 Linux 2.4.19 起)

SIGILL
ILL_ILLOPC非法操作碼
ILL_ILLOPN非法運算元
ILL_ILLADR非法定址模式
ILL_ILLTRP非法陷阱
ILL_PRVOPC特權操作碼
ILL_PRVREG特權暫存器
ILL_COPROC協處理器錯誤
ILL_BADSTK內部堆疊錯誤

SIGFPE
FPE_INTDIV整數除以零
FPE_INTOVF整數溢位
FPE_FLTDIV浮點除以零
FPE_FLTOVF浮點溢位
FPE_FLTUND浮點下溢
FPE_FLTRES浮點結果不精確
FPE_FLTINV浮點無效操作
FPE_FLTSUB下標越界

SIGSEGV
SEGV_MAPERR地址未對映到物件
SEGV_ACCERR對映物件的許可權無效

SIGBUS
BUS_ADRALN地址對齊無效
BUS_ADRERR不存在的物理地址
BUS_OBJERR特定於物件的硬體錯誤

SIGTRAP
TRAP_BRKPT程序斷點
TRAP_TRACE程序跟蹤陷阱

SIGCHLD
CLD_EXITED子程序已退出
CLD_KILLED子程序被殺死
CLD_DUMPED子程序異常終止
CLD_TRAPPED跟蹤的子程序已陷入
CLD_STOPPED子程序已停止
CLD_CONTINUED已停止的子程序已繼續(自 Linux 2.6.9 起)

SIGPOLL
POLL_IN資料輸入可用
POLL_OUT輸出緩衝區可用
POLL_MSG輸入訊息可用
POLL_ERRI/O 錯誤
POLL_PRI高優先順序輸入可用
POLL_HUP裝置斷開連線

返回值

sigaction() 成功時返回 0,錯誤時返回 -1。

錯誤

標籤描述
EFAULT actoldact 指向的記憶體不是程序地址空間的有效部分。
EINVAL 指定了無效訊號。如果嘗試更改 SIGKILLSIGSTOP 的操作,也會生成此錯誤,因為這兩個訊號無法捕獲或忽略。

備註

根據 POSIX,程序在忽略了未由 kill() 或 raise() 生成的 SIGFPESIGILLSIGSEGV 訊號後的行為未定義。整數除以零的結果未定義。在某些體系結構上,它會生成 SIGFPE 訊號。(同樣,將最負整數除以 -1 也可能生成 SIGFPE。)忽略此訊號可能導致無限迴圈。

POSIX.1-1990 不允許將 SIGCHLD 的操作設定為 SIG_IGN。POSIX.1-2001 允許這種可能性,以便可以忽略 SIGCHLD 以防止建立殭屍程序(參見 wait(2))。然而,忽略 SIGCHLD 的歷史 BSD 和 System V 行為有所不同,因此確保終止的子程序不成為殭屍程序的唯一完全可移植的方法是捕獲 SIGCHLD 訊號並執行 wait(2) 或類似操作。

POSIX.1-1990 僅指定了 SA_NOCLDSTOP。POSIX.1-2001 添加了 SA_NOCLDWAITSA_RESETHANDSA_NODEFERSA_SIGINFO。在打算用於較舊 Unix 實現的應用程式中,使用 sa_flags 中的這些後幾個值的可移植性可能較差。

Linux 2.2 中添加了對 SA_SIGINFO 的支援。

SA_RESETHAND 標誌與同名的 SVr4 標誌相容。

SA_NODEFER 標誌在核心 1.3.9 及更高版本下與同名的 SVr4 標誌相容。在較舊的核心上,Linux 實現允許接收任何訊號,而不僅僅是我們正在安裝的訊號(有效地覆蓋了任何 sa_mask 設定)。

sigaction() 可以使用空第二個引數呼叫以查詢當前訊號處理程式。它還可以透過使用空第二個和第三個引數呼叫它來檢查給定訊號對於當前機器是否有效。

無法阻止 SIGKILLSIGSTOP(透過在 sa_mask 中指定它們)。對此類嘗試會靜默忽略。

有關操作訊號集的詳細資訊,請參見 sigsetops(3)。

錯誤

在核心版本 2.6.13 及之前,在sa_flags中指定SA_NODEFER不僅會阻止在處理程式執行期間遮蔽傳遞的訊號,還會阻止sa_mask中指定的訊號。此錯誤已在核心 2.6.14 中修復。

符合標準

POSIX.1-2001, SVr4。

未公開文件

在引入SA_SIGINFO之前,還可以透過使用第二個引數型別為struct sigcontextsa_handler獲取一些其他資訊。有關詳細資訊,請參閱相關的核心原始碼。此用法現已過時。

參見



previous next Printer Friendly

廣告


  

廣告



廣告