信號掩碼——The signal mask

 

一. linux內部用一個128個字節(多個unsigned long)的結構(sigset_t)表示信號的掩碼,在i386平臺上就是128/4=32個long,每位對應一個信號的掩碼,最大支持128*8 = 1024個信號。現在只有64個信號,所以只要考慮最前面的兩個long就可以了。
sigset_t mask;
unsigned long *pl = (unsigned long*)&mask;
pl[0]和pl[1]就表示當前64個信號的掩碼,如果對應信號的那位=1,表示信號被屏蔽,發信號不會到達那個進程(線程)。=0,則相反。可以用sigfillset,sigaddset,sigemptyset等函數設置,這些函數定義在glibc的signal目錄中.. 注意:9(SIGKILL), 19(SIGSTOP),
32(不支持),33(不支持)這幾個信號是不能屏蔽的。
(2. linux線程的特性:無論在哪個線程中定義信號處理函數都是一樣的,同一個信號處理函數只能有一個,如果定義了多個,就會覆蓋前一個。如果創建子線程以前設置了掩碼,那麼子線程中自動繼承這個掩碼。可以在子線程中重新設置掩碼。這樣可以實現把特定信號分派給指定線程處理的功能。

二、信號掩碼 在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()系統調用來檢查是否有掛起的阻塞信號。

發佈了65 篇原創文章 · 獲贊 110 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章