Linux系統程式設計—訊號集操作函式
阿新 • • 發佈:2020-10-07
先來回顧一下**未決訊號集**是怎麼回事。
訊號從產生到抵達目的地,叫作**訊號遞達**。而訊號從產生到遞達的中間狀態,叫作訊號的**未決狀態**。產生未決狀態的原因有可能是訊號受到阻塞了,也就是**訊號遮蔽字**(或稱阻塞訊號集,mask)對應位被置1。阻塞訊號集和未決訊號集均是由核心維護的,整個過程如下圖示:
![img](https://img2020.cnblogs.com/other/1218435/202010/1218435-20201007115343757-249456831.webp)
我們有時需要遮蔽某個訊號,就需要去修改阻塞訊號集。那麼,我們該如何修改阻塞訊號集?系統提供的一個方法是,我們**先建立一個跟阻塞訊號集一樣的集合,再利用它去修改阻塞訊號集。**
系統提供了一系列的**訊號集設定函式**。這些函式如下所示:
```
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
### 有收穫?希望老鐵們來個三連擊,給更多的人看到這