二 Linux進程間通信( 四 )


下面是信號集操作函數的原型:
#include <signal.h>int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset(sigset_t *set, int signum);int sigdelset(sigset_t *set, int signum);int sigismember(const sigset_t *set, int signum);

  • sigemptyset: 初始化set指向的信號集,將所有比特位置0
  • sigfillset: 初始化set指向的信號集,將所有比特位置1
  • sigaddset: 把set指向的信號集中signum信號對應的比特位置1
  • sigdelset: 把set指向的信號集中signum信號對應的比特位置0
  • sigismember: 判斷signum信號是否存在set指向的信號集中(本質是信號判斷對應位是否為1)
注意: 在實現這些函數之前,需要使用sigemptyset 或sigfillset對信號集進行初始化 。前四個函數的返回值是成功返回0 , 失敗返回-1 。最后一個函數的返回值是真返回1,假返回-1
阻塞信號集操作函數——sigprocmask:
#include<signal.h>int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);功能:檢查或修改信號阻塞集 , 根據how指定的方法對進程的阻塞集合進行修改,新的信號阻塞集由set指定,而原先的信號阻塞集合由oldset保存 。參數:how:信號阻塞集合的修改方法,有3種情況:SIG_BLOCK:向信號阻塞集合中添加set信號集 , 新的信號掩碼是set和舊信號掩碼的并集 。相當于mask=mask丨set 。SIG_UNBLOCK:從信號阻塞集合中刪除set信號集,從當前信號掩碼中去除set中的信號 。相當于mask=mask&~set 。SIG_SETMASK:將信號阻塞集合設為set信號集,相當于原來信號阻塞集的內容清空 , 然后按照set中的信號重新設置信號阻塞集 。相當于mask=set 。set:要操作的信號集地址 。若set為NULL,則不改變信號阻塞集合 , 函數只把當前信號阻塞集合保存到oldset中 。oldset: 保存原先信號阻塞集地址 。返回值:成功:0失?。?1未決信號集操作函數——sigpending:
#include<signal.h>int sigpending(sigset_t *set);功能:讀取當前進程的未決信號集參數:set:未決信號集返回值:成功:0失敗:-1代碼示例:
實驗一:把進程中信號屏蔽字2號信號進行阻塞,然后每隔1s對未決信號集進行打印,觀察現象 。
#include <stdio.h>#include <unistd.h>#include <signal.h>void PrintPending(sigset_t* pend){int i = 0;for (i = 1; i < 32; ++i){if (sigismember(pend, i)){printf("1");}else{printf("0");}}printf("\n");}int main(){sigset_t set, oset;sigset_t pending;// 使用系統函數對信號集進行初始化sigemptyset(&set);sigemptyset(&oset);sigemptyset(&pending);// 阻塞2號信號// 先用系統函數對set信號集進行設置sigaddset(&set, 2);// 使用sigprocmask函數更改進程的信號屏蔽字// 第一個參數,三個選項:SIG_BLOCK(mask |= set) SIG_UNBLOCK(mask &= ~set) SIG_SETMASK(mask = set)sigprocmask(SIG_BLOCK, &set, &oset);int flag = 1; // 表示已經阻塞2號信號int count = 0;while (1){// 使用sigpending函數獲取pending信號集sigpending(&pending);// 打印pending位圖PrintPending(&pending);sleep(1);}return 0;}運行結果如下:
可以看到,進程收到2號信號時,且該信號被阻塞 , 處于未決狀態,未決信號集中2號信號對應的比特位由0置1
二 Linux進程間通信

文章插圖
實例2: 將上面的代碼進行修改,進行運行10s后,我們將信號屏蔽字中2號信號解除屏蔽
【二 Linux進程間通信】#include <stdio.h>#include <unistd.h>#include <signal.h>void PrintPending(sigset_t* pend){int i = 0;for (i = 1; i < 32; ++i){if (sigismember(pend, i)){printf("1");}else{printf("0");}}printf("\n");}int main(){sigset_t set, oset;sigset_t pending;// 使用系統函數對信號集進行初始化sigemptyset(&set);sigemptyset(&oset);sigemptyset(&pending);// 阻塞2號信號// 先用系統函數對set信號集進行設置sigaddset(&set, 2);// 使用sigprocmask函數更改進程的信號屏蔽字// 第一個參數,三個選項:SIG_BLOCK(mask |= set) SIG_UNBLOCK(mask &= ~set) SIG_SETMASK(mask = set)sigprocmask(SIG_BLOCK, &set, &oset);int flag = 1; // 表示已經阻塞2號信號int count = 0;while (1){// 使用sigpending函數獲取pending信號集 sigpending(&pending); // 打印pending位圖 PrintPending(&pending); if (++count == 10){// 兩種方法都可以sigprocmask(SIG_UNBLOCK, &set, &oset);//sigprocmask(SIG_SETMASK, &oset, NULL); }sleep(1);}return 0;}運行結果如下:
二 Linux進程間通信

文章插圖
信號2被阻塞之后就變成了未決狀態,當該信號從阻塞集合中解除的時候,該信號就會被處理,該信號被處理后 , 該信號的未決信號集的標志位將從1置為0 。

推薦閱讀