讓我們先回顧一下未決訊號集是什麼。當訊號從產生到抵達目的地時,這個過程稱為訊號遞達。而訊號從產生到遞達的中間狀態,則稱為訊號的未決狀態。產生未決狀態的原因可能是訊號被阻塞,也就是訊號屏蔽字(或阻塞訊號集)中的對應位元被置為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
範例:把所有常規訊號的未決狀態列印至螢幕。
#include #include #include void printPending(sigset_t *set) { int i = 0; for (i = 0; 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 + \ 将产生SIGQUIT信号 sigprocmask(SIG_BLOCK, &set, &oldset); while (1) { sigpending(&pendset); printPending(&pendset); // 写一个函数打印未决信号集 sleep(1); } }
以上是詳解Linux訊號集操作函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!