【Linux】信號的處理以及信號集操作函數

首先來再次看看這張圖:

sigset_t

從上圖來看,每個信號只有一個bit的未決標誌,非0即1,不記錄該信號產生了多少次,阻塞標誌也是這樣表示的。因此,未決和阻塞標誌可以用相同的數據類型sigset_t來存儲,sigset_t稱爲信號集,這個類型可以表示每個信號的“有效”或“無效”狀態,在阻塞信號集中“有效”和“無效”的含義是該信號是否被阻塞,而在未決信號集中“有效”和“無效”的含義是該信號是否處於未決狀態。

阻塞信號集也叫做當前進程的信號屏蔽字(Signal Mask),這裏的“屏蔽”應該理解爲阻塞而不是忽略。不能對sigset_t進行位操作,去修改裏面的內容,因爲我們不知道他的底層裏面都存放的是什麼,它只是幫助我們拿到操作系統底層的數據,因此我們要對位圖進行操作時必須要使用操作系統提供的信號集操作函數。

信號集操作函數

sigset_t類型對於每種信號用一個bit表示“有效”或“無效”狀態,至於這個類型內部如何存儲這些bit則依賴於系統
實現,從使用者的角度是不必關心的,使用者只能調用以下函數來操作sigset_ t變量,而不應該對它的內部數據做
任何解釋,比如用printf直接打印sigset_t變量是沒有意義的。

#include <signal.h>
1.int sigemptyset(sigset_t *set); //初始化信號集、清空
2.int sigfillset(sigset_t *set); //填滿信號集
3.int sigaddset (sigset_t *set, int signo); //把某個信號添加到信號集
4.int sigdelset(sigset_t *set, int signo); //刪除信號集中的某個信號
5.int sigismember(const sigset_t *set, int signo); //判斷一個信號是否在信號集中
  • 函數sigemptyset初始化set所指向的信號集,使其中所有信號的對應bit清零,表示該信號集不包含 任何有效信號。
  • 函數sigfillset初始化set所指向的信號集,使其中所有信號的對應bit置位,表示 該信號集的有效信號包括系統支持的所有信號。
  • 注意,在使用sigset_ t類型的變量之前,一定要調 用sigemptyset或sigfillset做初始化,使信號集處於確定的狀態。初始化sigset_t變量之後就可以在調用sigaddset和sigdelset在該信號集中添加或刪除某種有效信號。

這四個函數都是成功返回0,出錯返回-1。sigismember是一個布爾函數,用於判斷一個信號集的有效信號中是否包含
某種 信號,若包含則返回1,不包含則返回0,出錯返回-1。

sigprocmask

調用函數sigprocmask可以讀取或更改進程的信號屏蔽字(阻塞信號集)。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
返回值:若成功則爲0,若出錯則爲-1

如果oset是非空指針,則讀取進程的當前信號屏蔽字通過oset參數傳出。如果set是非空指針,則更改進程的信號屏蔽字,參數how指示如何更改。如果oset和set都是非空指針,則先將原來的信號屏蔽字備份到oset裏,然後根據set和how參數更改信號屏蔽字。假設當前的信號屏蔽字爲mask,下表說明了how參數的可選值。

SIG_BLOCK set包含了我們希望添加到當前信號屏蔽字的信號,相當於mask=mask|set
SIG_UNBLOCK set包含了我們希望從當前信號屏蔽字中解除阻塞的信號,相當於mask=mask&~set
SIG_SETMASK 設置當前信號屏蔽字爲set所指向的值,相當於mask=set

如果調用sigprocmask解除了對當前若干個未決信號的阻塞,則在sigprocmask返回前,至少將其中一個信號遞達。

sigpending

讀取當前進程的未決信號集,通過set參數傳出。

#include <signal.h>
int sigpending(sigset_t *set);

 

代碼實例

輸出結果

具體代碼:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <signal.h>
  4 void handler(int signo){
  5     printf("Get a Signal No. is%d\n",signo);
  6 }
  7 void show(sigset_t *pending){
  8     int i = 1;
  9     for( ;i<= 31;i++){
 10         if(sigismember(pending, i)){
 11             printf("1");
 12         }else{
 13             printf("0");
 14         }
 15     }
 16     printf("\n");
 17 }
 18 int main(){
 19     sigset_t set, oset;
 20     sigemptyset(&set);
 21     sigemptyset(&oset);
 22     sigaddset(&set , 2);
 23     sigprocmask(SIG_SETMASK, &set, &oset);
 24     signal(2, handler);
 25     sigset_t pending;
 26     int i = 15;
 27     while(1) {
 28         sigpending(&pending);
 29         show(&pending);
 31         if(i-- == 0){
 32             sigprocmask(SIG_SETMASK, &oset, NULL);
 33         }
 34     }
 35     return 0;
 36 }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章