Linux系統(tǒng)編程—信號(hào)集操作函數(shù)
先來(lái)回顧一下未決信號(hào)集是怎么回事。
信號(hào)從產(chǎn)生到抵達(dá)目的地,叫作信號(hào)遞達(dá)。而信號(hào)從產(chǎn)生到遞達(dá)的中間狀態(tài),叫作信號(hào)的未決狀態(tài)。產(chǎn)生未決狀態(tài)的原因有可能是信號(hào)受到阻塞了,也就是信號(hào)屏蔽字(或稱阻塞信號(hào)集,mask)對(duì)應(yīng)位被置1。阻塞信號(hào)集和未決信號(hào)集均是由內(nèi)核維護(hù)的,整個(gè)過(guò)程如下圖示:
我們有時(shí)需要屏蔽某個(gè)信號(hào),就需要去修改阻塞信號(hào)集。那么,我們?cè)撊绾涡薷淖枞盘?hào)集?系統(tǒng)提供的一個(gè)方法是,我們先創(chuàng)建一個(gè)跟阻塞信號(hào)集一樣的集合,再利用它去修改阻塞信號(hào)集。
系統(tǒng)提供了一系列的信號(hào)集設(shè)定函數(shù)。這些函數(shù)如下所示:
- sigset_t set;
- 信號(hào)集數(shù)據(jù)類型,本質(zhì)是typedef unsigned long sigset_t;
- int sigemptyset(sigset_t *set);
- 將某個(gè)信號(hào)集清0
- int sigfillset(sigset_t *set);
- 將某個(gè)信號(hào)集置1
- int sigaddset(sigset_t *set, int signum);
- 將某個(gè)信號(hào)加入信號(hào)集int sigdelset(sigset_t *set, int signum);
- 將某個(gè)信號(hào)清出信號(hào)集以上幾個(gè)函數(shù)返回值均是:成功:0;失?。?1
- int sigismember(const sigset_t *set, int signum);
- 判斷某個(gè)信號(hào)是否在信號(hào)集中返回值:在集合:1;不在:0;出錯(cuò):-1
使用以上這些函數(shù)創(chuàng)建完信號(hào)集后,要如何去改變阻塞信號(hào)集呢?系統(tǒng)又提供了一個(gè)函數(shù):sigprocmask函數(shù)。
sigprocmask函數(shù)可以用來(lái)屏蔽信號(hào),也可以用來(lái)解除屏蔽信號(hào),其本質(zhì)就是利用我們創(chuàng)建的信號(hào)集去改變阻塞信號(hào)集。
函數(shù)原型:
- int sigprocmask(int how, const sigset_t set, sigset_t oldset);
返回值:
成功:0;失?。?1,設(shè)置errno
參數(shù)解釋:
- set:傳入?yún)?shù),是一個(gè)位圖,set中哪位置1,就表示當(dāng)前進(jìn)程屏蔽哪個(gè)信號(hào)。
- oldset:傳出參數(shù),保存舊的信號(hào)屏蔽集。這個(gè)與setitimer有點(diǎn)相似。
how參數(shù)取值:
假設(shè)當(dāng)前的信號(hào)屏蔽字為mask
- SIG_BLOCK:當(dāng)how設(shè)置為此值,set表示需要屏蔽的信號(hào)。相當(dāng)于 mask = mask | set
- SIG_UNBLOCK:當(dāng)how設(shè)置為此,set表示需要解除屏蔽的信號(hào)。相當(dāng)于 mask = mask & ~set
- SIG_SETMASK:當(dāng)how設(shè)置為此,set表示用于替代原始屏蔽及的新屏蔽集。相當(dāng)于 mask = set若,調(diào)用sigprocmask解除了對(duì)當(dāng)前若干個(gè)信號(hào)的阻塞,則在sigprocmask返回前,至少將其中一個(gè)信號(hào)遞達(dá)。
我們?nèi)绾巫x取未決信號(hào)集?系統(tǒng)提供了sigpending函數(shù)。
函數(shù)原型:
- int sigpending(sigset_t *set);
參數(shù)說(shuō)明:set傳出參數(shù)。
返回值:
返回值:成功:0;失?。?1,設(shè)置errno
例:把所有常規(guī)信號(hào)的未決狀態(tài)打印至屏幕。
- #include
- #include
- #include
- void printPending(sigset_t *set)
- {
- int i = 0;
- for (i = 0; i < 32; i++) {
- if (sigismember(set, i) == 1)
- printf("1");
- else
- printf("0");
- }
- printf("\n");
- }
- int main()
- {
- sigset_t set, oldset, pendset;
- sigemptyset(&set);
- sigaddset(&set, SIGQUIT); // ctrl + \ 將產(chǎn)生SIGQUIT信號(hào)
- sigprocmask(SIG_BLOCK, &set, &oldset);
- while (1) {
- sigpending(&pendset);
- printPending(&pendset); // 寫一個(gè)函數(shù)打印未決信號(hào)集
- sleep(1);
- }
- }
本文授權(quán)轉(zhuǎn)載自公眾號(hào)「良許Linux」。良許,世界500強(qiáng)外企Linux開(kāi)發(fā)工程師,公眾號(hào)里分享大量Linux干貨,歡迎關(guān)注!