1. 程式人生 > >Linux訊號 五 訊號掛起與訊號掩碼操作介面集

Linux訊號 五 訊號掛起與訊號掩碼操作介面集

    A signal may be blocked, which means that it will not be delivered
until it is later unblocked.  Between the time when it is generated
and when it is delivered a signal is said to be pending.
    訊號可以被阻塞,除非阻塞被解除否則不能將訊號傳遞給程序。從訊號產生到訊號被解除
阻塞這一段時間稱之為掛起。
    Each thread in a process has an independent signal mask, which
indicates the set of signals that the thread is currently blocking.
    程序內的每個執行緒都有一個獨立的訊號掩碼,訊號掩碼是一組訊號集合,表明當前執行緒
阻塞的訊號。

Linux提供了一個新的資料結構用來實現訊號掩碼的功能:訊號集。多個訊號組成的集合被稱為訊號集,其資料型別為sigset_t。在Linux的實現中,sigset_t型別是位掩碼,每一個位元代表一個訊號。

相關操作介面包括訊號集初始化、新增、刪除、設定訊號掩碼等:

sigemptyset,  sigfillset,  sigaddset,  sigdelset, sigismember
sigprocmask, pthread_sigmask

#include <signal.h>

/**
 *  初始化一個空的未包含任何訊號的訊號集。
 *  成功返回0,失敗返回-1並置errno 
 */
int sigemptyset(sigset_t *set);

/**
 *  初始化一個包含任何訊號的訊號集。
 *  成功返回0,失敗返回-1並置errno 
 */
int sigfillset(sigset_t *set);

/**
 *  向訊號集中新增一個訊號。
 *  成功返回0,失敗返回-1並置errno 
 */
int sigaddset(sigset_t *set, int signum);


/**
 *  從訊號集中刪除一個訊號。
 *  成功返回0,失敗返回-1並置errno 
 */
int sigdelset(sigset_t *set, int signum);


/**
 *  判斷該訊號是否在訊號集中
 *  屬於返回1,不屬於返回0,出錯返回-1並置errno
 */
int sigismember(const sigset_t *set, int signum);

/**
 *  將當前執行緒的訊號集讀取到set結構體中
 *  成功返回0,失敗返回-1並置errno
 */
int sigpending(sigset_t *set);


Glibc擴充套件函式
如果定義了 _GNU_SOURCE 巨集,signal.h還提供了額外三個引數用於操作訊號集,不過
這些都是非標準的函式(其它系統可能有類似的實現),不能用於移植程式的開發中

/**
 *  判斷訊號集是否為空
 *  為空返回1,否則返回0
 */
int sigisemptyset(const sigset_t *set);

/**
 *  取left 和 right的並集,並存儲到dest結構體中
 *  成功返回0,失敗返回-1並置errno
 */
int sigorset(sigset_t *dest, const sigset_t *left,
                     const sigset_t *right);
/**
 *  取left 和 right的交集,並存儲到dest結構體中
 *  成功返回0,失敗返回-1並置errno
 */
int sigandset(sigset_t *dest, const sigset_t *left,
                     const sigset_t *right);

/**
 *  獲取或設定程序的阻塞訊號掩碼
 *
 *  根據引數how的值,提供了三種用於改變程序的阻塞訊號掩碼方式
 *
 *  SIG_BLOCK:新的程序訊號掩碼是當前訊號掩碼與set指向訊號集的並集,相當於在當前訊號集
 *  掩碼中增加set的訊號。
 *
 *  SIG_UNBLOCK: 新的程序訊號掩碼是當前訊號掩碼與set指向訊號集的補集的交集,相當於從
 *  當前訊號掩碼中刪除set中訊號,解除對其的遮蔽。
 *
 *  SIG_SETMASK : 直接把程序的訊號掩碼設定成set指向的訊號集。
 *
 *  如果引數oldset不為NULL,之前的訊號掩碼配置將會儲存到該指標中。
 *  如果引數set為NULL的話,相當於不做任何改變。
 *
 *  另外多執行緒中使用該函式的結果將是未定義的,多執行緒中最好使用pthread_sigmask()介面
 *
 *  成功返回0,失敗返回-1並置errno
 */
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

/**
 *  該函式功能和sigprocmask一樣,只不過是用在多執行緒中,用於改變呼叫執行緒的訊號掩碼集。
 *  
 *  成功返回0,失敗返回錯誤碼,編譯連結的時候加上-pthread選項。
 */
#include <signal.h>
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);

參考資料

1. 《Linux環境程式設計,從應用到核心》高峰,李彬著

2. man signal : http://www.man7.org/linux/man-pages/man7/signal.7.html

    man sigsetops : http://www.man7.org/linux/man-pages/man3/sigsetops.3.html