信號掩碼

在POSIX下,每個進程有一個信號掩碼(signal mask)。簡單地說,信號掩碼是一個“點陣圖”,其中每一位都對應著一種信號。

信號掩碼
如果點陣圖中的某一位為1,就表示在執行當前信號的處理程式期間相應的信號暫時被“禁止”,使得在執行的過程中不會嵌套地回響那種信號。
為什麼對某一信號進行禁止呢?我們來看一下對CTRL_C的處理。大家知道,當一個程式正在運行時,在鍵盤上按一下CTRL_C,核心就會向相應的進程發出一個SIGINT 信號,而對這個信號的默認操作就是通過do_exit()結束該進程的運行。但是,有些應用程式可能對CTRL_C有自己的處理,所以就要為SIGINT另行設定一個處理程式,使它指向應用程式中的一個函式,在那個函式中對CTRL_C這個事件作出回響。但是,在實踐中卻發現,兩次CTRL_C事件往往過於密集,有時候剛剛進入第一個信號的處理程式,第二個SIGINT信號就到達了,而第二個信號的默認操作是殺死進程,這樣,第一個信號的處理程式根本沒有執行完。為了避免這種情況的出現,就在執行一個信號處理程式的過程中將該種信號自動禁止掉。所謂“禁止”,與將信號忽略是不同的,它只是將信號暫時“遮蓋”一下,一旦禁止去掉,已到達的信號又繼續得到處理。
Linux核心中有一個專門的函式集合來執行設定和修改信號掩碼,它們放在kernel/signal.c中,其函式形式和功能如下:
函式形式 功能 int sigemptyset(sigset_t *mask) 清所有信號掩碼的阻塞標誌
int sigfillset(sigset_t *mask, int signum) 設定所有信號掩碼的
阻塞標誌
int sigdelset(sigset_t *mask, int signum) 刪除個別信號阻塞
int sigaddset(sigset_t *mask, int signum) 增加個別信號阻塞
int sigisnumber(sigset_t *mask, int signum) 確定特定的信號是否在掩
碼中被標誌為阻塞。
另外,進程也可以利用sigprocmask() 系統調用改變和檢查自己的信號掩碼的值,其實現代碼在kernel/signal.c中,原型為:
int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
其中,set是指向信號掩碼的指針,進程的信號掩碼是根據參數how的取值設定成set;參數how的取值及含義如下:
SIG_BOLCK set規定附加的阻塞信號;
SIG_UNBOCK set規定一組不予阻塞的信號
SIG_SETBLOCK set變成新進程的信號掩碼
用一段代碼來說明這個問題
switch (how) {
case SIG_BLOCK:
current->blocked |= new_set;
break;
case SIG_UNBLOCK:
current->blocked &= ~new_set;
break;
case SIG_SETMASK:
current->blocked = new_set;
break;
default:
return -EINVAL;
}
其中current為指向當前進程task_struc結構的指針。
第三個參數oset也是指向信號掩碼的指針,它將包含以前的信號掩碼值,使得在必要的時候,可以恢復它。
進程可以用sigpending()系統調用來檢查是否有掛起的阻塞信號。

相關詞條

熱門詞條

聯絡我們