解析Linux訊號集操作函式

大雄45發表於2020-10-21
導讀 先來回顧一下未決訊號集是怎麼回事。訊號從產生到抵達目的地,叫作訊號遞達。而訊號從產生到遞達的中間狀態,叫作訊號的未決狀態。產生未決狀態的原因有可能是訊號受到阻塞了,也就是訊號遮蔽字(或稱阻塞訊號集,mask)對應位被置1。阻塞訊號集和未決訊號集均是由核心維護的,整個過程如下圖示:

解析Linux訊號集操作函式解析Linux訊號集操作函式

我們有時需要遮蔽某個訊號,就需要去修改阻塞訊號集。那麼,我們該如何修改阻塞訊號集?系統提供的一個方法是,我們先建立一個跟阻塞訊號集一樣的集合,再利用它去修改阻塞訊號集。

系統提供了一系列的訊號集設定函式。這些函式如下所示:

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 < 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 + \ 將產生SIGQUIT訊號
    sigprocmask(SIG_BLOCK, &set, &oldset);
    while (1) {
        sigpending(&pendset);
        printPending(&pendset);     // 寫一個函式列印未決訊號集
        sleep(1);
    }
}

原文來自:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2728384/,如需轉載,請註明出處,否則將追究法律責任。

相關文章