Linux系統編程—信號集操作函數
- 2020 年 10 月 7 日
- 筆記
先來回顧一下未決信號集是怎麼回事。
信號從產生到抵達目的地,叫作信號遞達。而信號從產生到遞達的中間狀態,叫作信號的未決狀態。產生未決狀態的原因有可能是信號受到阻塞了,也就是信號屏蔽字(或稱阻塞信號集,mask)對應位被置1。阻塞信號集和未決信號集均是由內核維護的,整個過程如下圖示:
我們有時需要屏蔽某個信號,就需要去修改阻塞信號集。那麼,我們該如何修改阻塞信號集?系統提供的一個方法是,我們先創建一個跟阻塞信號集一樣的集合,再利用它去修改阻塞信號集。
系統提供了一系列的信號集設定函數。這些函數如下所示:
sigset_t set;
信號集數據類型,本質是typedef unsigned long sigset_t;
int sigemptyset(sigset_t *set);
將某個信號集清0
int sigfillset(sigset_t *set);
將某個信號集置1
int sigaddset(sigset_t *set, int signum);
將某個信號加入信號集
int sigdelset(sigset_t *set, int signum);
將某個信號清出信號集
以上幾個函數返回值均是:成功:0;失敗:-1
int sigismember(const sigset_t *set, int signum);
判斷某個信號是否在信號集中
返回值:在集合:1;不在:0;出錯:-1
使用以上這些函數創建完信號集後,要如何去改變阻塞信號集呢?系統又提供了一個函數:sigprocmask函數。
sigprocmask函數可以用來屏蔽信號,也可以用來解除屏蔽信號,其本質就是利用我們創建的信號集去改變阻塞信號集。
函數原型:
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
返回值:
成功:0;失敗:-1,設置errno
參數解釋:
set:傳入參數,是一個位圖,set中哪位置1,就表示當前進程屏蔽哪個信號。
oldset:傳出參數,保存舊的信號屏蔽集。這個與setitimer有點相似。
how參數取值:
假設當前的信號屏蔽字為mask
1.SIG_BLOCK:當how設置為此值,set表示需要屏蔽的信號。相當於 mask = mask | set
2.SIG_UNBLOCK:當how設置為此,set表示需要解除屏蔽的信號。相當於 mask = mask & ~set
3.SIG_SETMASK:當how設置為此,set表示用於替代原始屏蔽及的新屏蔽集。相當於 mask = set若,調用sigprocmask解除了對當前若干個信號的阻塞,則在sigprocmask返回前,至少將其中一個信號遞達。
我們如何讀取未決信號集?系統提供了sigpending函數。
函數原型:
int sigpending(sigset_t *set);
參數說明:
set傳出參數。
返回值:
返回值:成功:0;失敗:-1,設置errno
例:把所有常規信號的未決狀態打印至屏幕。
1#include
2#include
3#include
4
5void printPending(sigset_t *set)
6{
7 int i = 0;
8
9 for (i = 0; i < 32; i++) {
10 if (sigismember(set, i) == 1)
11 printf("1");
12 else
13 printf("0");
14 }
15 printf("\n");
16}
17
18int main()
19{
20 sigset_t set, oldset, pendset;
21 sigemptyset(&set);
22 sigaddset(&set, SIGQUIT); // ctrl + \ 將產生SIGQUIT信號
23 sigprocmask(SIG_BLOCK, &set, &oldset);
24 while (1) {
25 sigpending(&pendset);
26 printPending(&pendset); // 寫一個函數打印未決信號集
27 sleep(1);
28 }
29}
公眾號:良許Linux