sigaction() - Unix 和 Linux 系統呼叫
廣告
名稱sigaction - 檢查和更改訊號操作語法
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 描述sigaction() 系統呼叫用於更改程序在收到特定訊號時採取的操作。
signum 指定訊號,可以是任何有效的訊號,除了 SIGKILL 和 SIGSTOP。 如果 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_handler 和 sa_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 | | 如果 signum 是 SIGCHLD,則在子程序停止(即,當它們收到 SIGSTOP、SIGTSTP、SIGTTIN 或 SIGTTOU 中的一個)或恢復(即,它們收到 SIGCONT)時,不接收通知(參見 wait(2))。 |
SA_NOCLDWAIT | | (Linux 2.6 及更高版本)如果 signum 是 SIGCHLD,則當子程序終止時,不要將其轉換為殭屍程序。另請參見 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_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 */
}
|
si_signo、si_errno 和 si_code 對所有訊號都已定義。(si_signo 在 Linux 上未使用。)結構的其餘部分可能是一個聯合體,因此只能讀取對給定訊號有意義的欄位。POSIX.1b 訊號和 SIGCHLD 將填充 si_pid 和 si_uid。SIGCHLD 還填充 si_status、si_utime 和 si_stime。si_int 和 si_ptr 由 POSIX.1b 訊號的發件人指定。SIGILL、SIGFPE、SIGSEGV 和 SIGBUS 將 si_addr 填充為錯誤地址。SIGPOLL 填充 si_band 和 si_fd。
si_code 指示傳送此訊號的原因。它是一個值,而不是一個位掩碼。任何訊號可能出現的值在此表中列出
si_code |
值 | 訊號來源 |
SI_USER | kill()、sigsend() 或 raise() |
SI_KERNEL | 核心 |
SI_QUEUE | sigqueue() |
SI_TIMER | POSIX 定時器過期 |
SI_MESGQ | POSIX 訊息佇列狀態更改(自 Linux 2.6.6 起) |
SI_ASYNCIO | AIO 完成 |
SI_SIGIO | 排隊的 SIGIO |
SI_TKILL | tkill() 或 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_ERR | I/O 錯誤 |
POLL_PRI | 高優先順序輸入可用 |
POLL_HUP | 裝置斷開連線 |
返回值
sigaction() 成功時返回 0,錯誤時返回 -1。錯誤
標籤 | 描述 |
EFAULT |
act 或 oldact 指向的記憶體不是程序地址空間的有效部分。 |
EINVAL | 指定了無效訊號。如果嘗試更改 SIGKILL 或 SIGSTOP 的操作,也會生成此錯誤,因為這兩個訊號無法捕獲或忽略。 |
備註
根據 POSIX,程序在忽略了未由 kill() 或 raise() 生成的 SIGFPE、SIGILL 或 SIGSEGV 訊號後的行為未定義。整數除以零的結果未定義。在某些體系結構上,它會生成 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_NOCLDWAIT、SA_RESETHAND、SA_NODEFER 和 SA_SIGINFO。在打算用於較舊 Unix 實現的應用程式中,使用 sa_flags 中的這些後幾個值的可移植性可能較差。 Linux 2.2 中添加了對 SA_SIGINFO 的支援。 SA_RESETHAND 標誌與同名的 SVr4 標誌相容。 SA_NODEFER 標誌在核心 1.3.9 及更高版本下與同名的 SVr4 標誌相容。在較舊的核心上,Linux 實現允許接收任何訊號,而不僅僅是我們正在安裝的訊號(有效地覆蓋了任何 sa_mask 設定)。
sigaction() 可以使用空第二個引數呼叫以查詢當前訊號處理程式。它還可以透過使用空第二個和第三個引數呼叫它來檢查給定訊號對於當前機器是否有效。 無法阻止 SIGKILL 或 SIGSTOP(透過在 sa_mask 中指定它們)。對此類嘗試會靜默忽略。 有關操作訊號集的詳細資訊,請參見 sigsetops(3)。 錯誤
在核心版本 2.6.13 及之前,在sa_flags中指定SA_NODEFER不僅會阻止在處理程式執行期間遮蔽傳遞的訊號,還會阻止sa_mask中指定的訊號。此錯誤已在核心 2.6.14 中修復。符合標準POSIX.1-2001, SVr4。未公開文件在引入SA_SIGINFO之前,還可以透過使用第二個引數型別為struct sigcontext的sa_handler獲取一些其他資訊。有關詳細資訊,請參閱相關的核心原始碼。此用法現已過時。參見
廣告
|