Linux 未決訊號集與訊號遮蔽字

嚇人的猿發表於2018-02-27

訊號集

​ 訊號集顧名思義就是訊號的集合,訊號集的型別為sigset_t,每一種訊號用1bit來表示,前面我們提到訊號有64種,那麼這個sigset_t型別至少佔64bit,可以通過sizeof(sigset_t)來檢視。

​ 每個程式的PCB程式控制塊中都有兩個訊號集,一個叫作未決訊號集,一個叫作訊號遮蔽字,訊號集的每一位不是0就是1,初始狀態下,兩個訊號集的值都為0。

​ 當有訊號傳遞到該程式的時候,未決訊號集的對應位設定為1,其他位不變,這個時候訊號只是傳遞到程式,並未被處理,叫作未決狀態。常規訊號在遞達之前產生多次只計一次,而實時訊號在遞達之前產生多次可以依次放在一個佇列裡。使用者只能獲取未決訊號集值,無法改變其值。

​ 未決訊號想要遞達程式的訊號處理函式(預設、忽略、自定義),還要經過訊號遮蔽字的過濾,一旦該訊號對應bit為1,則該訊號將阻塞,不能傳遞到訊號的處理函式。使用者可以設定獲取訊號遮蔽字的值。

  • 訊號集處理函式

#include <signal.h>
int sigemptyset(sigset_t *set) //將set每一位都置0
int sigfillset(sigset_t *set) //將set每一位都置1
int sigaddset(sigset_t *set, int signo) //將set中signo訊號對應的bit置1
int sigdelset(sigset_t *set, int signo) //將set中signo訊號對應的bit置0
int sigismember(const sigset_t *set, int signo) //判斷set中signo訊號對應bit是否為1,返回1或者0。

  • sigprocmask

    呼叫函式sigprocmask可以讀取或更改程式的訊號遮蔽字。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
/*
how引數:
    SIG_BLOCK set包含了我們希望新增到當前訊號遮蔽字的訊號,相當於mask=mask|set
    SIG_UNBLOCK set包含了我們希望從當前訊號遮蔽字中解除阻塞的訊號,相當於mask=mask&~set
    SIG_SETMASK 設定當前訊號遮蔽字為set所指向的值,相當於mask=set
set引數:傳入引數
oset引數:傳出引數,獲取原先的訊號遮蔽字,一般可以填0
返回值:若成功則為0,若出錯則為-1
*/

​ 如果呼叫sigprocmask解除了對當前若干個未決訊號的阻塞,則在sigprocmask返回前,至少將其中一個訊號遞達。

  • sigpending

讀取當前程式的未決訊號集

#include <signal.h>
int sigpending(sigset_t *set);
/*
通過set引數傳出。呼叫成功則返回0,出錯則返回-1。
*/
  • 綜合示例

#include <signal.h>
#include <stdio.h>
void printsigset(const sigset_t *set)
{
    int i;
    for (i = 1; i < 32; i++)
        if (sigismember(set, i) == 1)
            putchar('1');
        else
            putchar('0');
    puts("");
}
int main(void)
{
    sigset_t s, p;
    sigemptyset(&s);
    sigaddset(&s, SIGINT);  //將訊號集s中的SIGINT置為1
  
    sigprocmask(SIG_BLOCK, &s, NULL); //設定訊號遮蔽字
    while (1) 
    {
        sigpending(&p);  //獲取未決訊號集
        printsigset(&p); //列印未決訊號集
        sleep(1);
    }
    return 0;
}

相關文章