一. 阻塞信號
1.信號的相關概念
????(1) 遞達: 實際執行信號的處理動作稱為信號的遞達
????(2) 未決: 信號從產生到遞達之間的過程叫做信號的未決
????(3) 阻塞: 進程可以選擇阻塞某個信號, 被阻塞的信號產生時將保持在未決狀態, 直到進程解除該信號的屏蔽, 才執行遞達動作.
????(4) 阻塞和忽略的不同: 信號被阻塞就不會被遞達, 而信號被忽略是該信號遞達的一種方式
????(5) 信號遞達的幾種方式: 忽略, 默認處理, 自定義
二. 信號在內核中的表示
????
????每個信號都有兩個標志位表示該信號的阻塞和未決還有一個函數指針表示該信號的處理動作, 信號產生時,內核在進程控制塊中設置該信號的未決標識, 直到該信號遞達才清除該標志. 在圖上 SIGUP 信號未產生過, 也為阻塞過, 當它遞達時執行默認動作, SIGINT 信號產生過, 并且處于阻塞狀態, 該信號暫時不能被遞達, 直到被解除阻塞. SIGQUIT 未產生, 一旦產生, 該信號就被阻塞, 它的處理動作是自定義. 如果在進程解除對某信號的阻塞前, 信號產生過多次, 該信號該怎樣計算呢? POSIX.1 允許信號被遞達一次或者多次, Linux 中規定對于普通信號, 在遞達之前產生多次知己一次, 而對于實時信號遞達多次可以放在一個隊列里.
三. sigset_t
????由圖中可以看出, 每個信號只有一個 bit 位表示未決, 一個bit 位表示阻塞, 于是可以用 sigset_t 的數據類型來對兩者進行存儲. sigset_t 它是一個信號集, 用來表示該信號的有效或者無效. 在阻塞表中表示是否阻塞, 在未決表中表示該信號是否未決.阻塞信號集也叫做當前信號的屏蔽字
四. 相關接口函數
????1.信號集相關接口
??????????????????????
????(1)用于初始化set 所指向的所有信號集, 將 set 所指向的信號集中的所有信號的 bit 全部清零, 表示該信號集不含任何有效信號.
????(2)sigfillset 用于初始化set信號集所指向的所有信號, 將其中所有信號的 bit 位置位, 該信號集的有效信號包括該系統中支持的所有信號
????(3)使用 sigset_t 類型的 變量的時候一定要用 sigsetempty 以及 sigfillset 初始化, 使得信號集處于確定狀態, 初始化之后就可以調用 sigaddset 和 sigdelset 在該信號集中添加或者刪除 某個信號
????(4) sigismember 用來判斷某個信號集中是否包含某個信號, 如果有返回 1, 沒有返回 0, 調用失敗返回 -1.
????(5)不能對 sigset_t 類型的變量做任何解釋, 如打印等操作, 因為它是系統實現的使用者不必關心
????2. 阻塞信號集相關接口
????
????(1)用來讀取或者更改信號屏蔽字(阻塞的信號集), 成功時返回0, 出錯時返回 -1.
????(2)how 用來表示更改屏蔽字的方式
????(3)oldset 表示原有的阻塞信號集(信號屏蔽字), set 表示需要修改的信號屏蔽字(阻塞信號集).
????how 有三個取值, 假設當前的屏蔽字是mask 則SIG_BLOCK 相當于 mask = mask | set, SIG_UNBLOCK 相當于 mask = mask &~set, SIG_SETMASK 相當于 mask = set
????3. 未決信號集相關接口
????????????????????
????用于讀取當前進程的未決信號集, set 是一個輸出型參數, 有用戶自己設定. 調用成功返回0, 調用失敗返回 -1.
????4. 代碼演示
#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<unistd.h>void sigprint(sigset_t* set)
{if(set == NULL){return;}int i = 0;for(; i < 32; i++){if(sigismember(set, i)){putchar('1');}else{putchar('0');}}printf("\n");
}int main()
{sigset_t set, p;sigset_t oset;sigemptyset(&p);sigemptyset(&set);sigaddset(&set, SIGINT);sigprocmask(SIG_BLOCK, &set, &oset);int count = 10;while(count){sigpending(&p);sigprint(&p);sleep(1);count--;}sigprocmask(SIG_BLOCK, &oset, NULL);return 0;
}
????????????????????????
????此時發現當按 Ctrl + C 的時候進程不能停止, 因為Ctrl + C 是2 號信號, 該信號被阻塞, 當產生一個二號信號時, 操作系統將其放到未決狀態, 不能被遞達, 因此 Ctrl + C 已經能再終止進程, 當按一下 Ctrl + \ (3)號信號,可以終止進程, 因為該進程沒有被阻塞.