1. 程式人生 > >對訊號掩碼和訊號集進行操作

對訊號掩碼和訊號集進行操作

每個程序都有一個訊號掩碼,它給出了當前程序想要阻塞的訊號的集合,訊號掩碼的型別為sigset_t。注意,阻塞訊號與忽略訊號的概念是不同的,程序阻塞訊號時,作業系統會在程序解除對該訊號的阻塞之前不會將訊號傳遞出去,但解除阻塞之後,程序還是會收到該訊號的。但是程序忽略訊號時,作業系統會將訊號傳遞出去,只不過時程序在處理時將該訊號忽略了而已。程序通過sigprocmask函式來阻塞一個訊號,通過sigaction來忽略一個訊號

對訊號掩碼sigset_t的操作有如下5個函式

  1. int sigaddset(sigset_t *set, int signo):將signo新增到set中
  2. int sigdelset(sigset_t *set, int signo):將signo從set中刪除
  3. int sigemptyset(sigset_t *set):將set初始化為不包含任何訊號
  4. int sigfillset(sigset_t *set):將set初始化為包含全部訊號
  5. int sigismember(sigset_t *set, int signo):判斷signo是否包含在set集合中

通過這5個函式,我們可以實現對sigset_t進行任意我們想要的操作

sigprocmask函式

我們通過該函式實現對訊號的阻塞操作,函式原型為:

int sigprocmase(int how, const sigset_t *set, sigset_t *oset)

set引數為操作的訊號集,oset引數不為空時,會返回修改之前的訊號掩碼,how指出修改訊號掩碼的方式:

  1. SIG_BLOCK:向當前被阻塞的訊號集中新增一個訊號集
  2. SIG_UNBLOCK:向當前被阻塞的訊號中刪除一個訊號集
  3. SIG_SETMASE:將制定的訊號集設定為被阻塞的訊號

注意:某些訊號(比如SIGSTOP和SIGKILL)是不可以被阻塞的,試圖阻塞這些訊號,系統會忽略這個請求而不會報告錯誤

sigaction函式

該函式允許呼叫程式檢查或指定與特定訊號相關的動作,原型如下:

int sigaction(int sig, const struct sigaction *act, struct sigaction oact);

引數sig用來指定動作的訊號碼,act用來指定要採取的動作,若該引數為NULL,則不會作改變;oact用來接受與訊號相關的前一個動作。

struct sigaction{

void (*sa_handler)(int);//SIG_DEF、SIG_IGN或者指向函式的指標

sigset_t sa_mask;//處理程式在執行過程中需要阻塞的額外的訊號

int sa_flags;//特殊的標誌符和選項

void (*sa_sigaction) (int, siginfo_t *, void *);//實時處理程式

}

sa_handler和sa_sigaction只能有一個有效,由sa_flags欄位的標誌符SA_SIGINFO指出誰有效。

注意:雖然我們可以使用signal函式來註冊訊號處理函式,但是在支援sigaction的版本中,我們應該用sigaction函式來代替它,因為後者要更安全,功能更強大。