#include <signal.h>
int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );
返回值:若成功則返回0,若出錯則返回-1
首先,若oset是非空指針,那麼進程的當前信號屏蔽字通過oset返回。
其次,若set是一個非空指針,則參數how指示如何修改當前信號屏蔽字。
how | 說明 |
SIG_BLOCK | 該進程新的信號屏蔽字是其當前信號屏蔽字和set指向信號集的並集。set包含了我們希望阻塞的附加信號 |
SIG_UNBLOCK | 該進程新的信號屏蔽字是其當前信號屏蔽字和set所指向信號集補集的交集。set包含了我希望解除阻塞的信號 |
SIG_SETMASK | 該進程新的信號屏蔽字將被set指向的信號集的值代替 |
如果set是空指針,則不改變該進程的信號屏蔽字,how的值也無意義。
直接通過代碼
#include <stdio.h>
#include <stdlib.h> //malloc
#include <unistd.h>
#include <signal.h>
//信號處理函數
void sig_quit(int signo)
{
printf("收到了SIGQUIT信號!\n");
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_BLOCK,NULL,&set);
//當前捕獲信號在被捕獲期間是被阻塞的.
if(sigismember(&set,SIGQUIT)) //測試一個指定的信號位是否被置位(爲1),測試的是newmask
{
printf("捕獲期間舊SIGQUIT信號被屏蔽了!\n");
}
else
{
printf("捕獲期間舊SIGQUIT信號沒有被屏蔽!!!!!!\n");
}
//在設置回默認
if(signal(SIGQUIT,SIG_DFL) == SIG_ERR)
{
printf("無法爲SIGQUIT信號設置缺省處理(終止進程)!\n");
exit(1);
}
}
int main(int argc, char *const *argv)
{
sigset_t newmask,oldmask,pendmask;
if(signal(SIGQUIT,sig_quit) == SIG_ERR) //註冊信號對應的信號處理函數,"ctrl+\"
{
printf("無法捕捉SIGQUIT信號!\n");
exit(1);
//退出程序,參數是錯誤代碼,0表示正常退出,非0表示錯誤,但具體什麼錯誤,沒有特別規定
}
sigemptyset(&newmask); //newmask信號集中所有信號都清0(表示這些信號都沒有來)
sigaddset(&newmask,SIGQUIT); //設置newmask信號集中的SIGQUIT信號位爲1,也就是說,再來SIGQUIT信號時,進程就收不到,設置爲1就是該信號被阻塞掉
printf("我要開始休息10秒了--------begin--\n");
sleep(10); //測試沒有屏蔽的時候處理信號
printf("我已經休息了10秒了--------end----!\n");
//再次註冊
if(signal(SIGQUIT,sig_quit) == SIG_ERR) //註冊信號對應的信號處理函數,"ctrl+\"
{
printf("無法捕捉SIGQUIT信號!\n");
exit(1);
//退出程序,參數是錯誤代碼,0表示正常退出,非0表示錯誤,但具體什麼錯誤,沒有特別規定
}
if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0) //第一個參數用了SIG_BLOCK表明設置 進程 新的信號屏蔽字 爲 “當前信號屏蔽字 和 第二個參數指向的信號集的並集
{
//一個 ”進程“ 的當前信號屏蔽字,剛開始全部都是0的;所以相當於把當前 "進程"的信號屏蔽字設置成 newmask(屏蔽了SIGQUIT);
//第三個參數不爲空,則進程老的(調用本sigprocmask()之前的)信號集會保存到第三個參數裏,用於後續,這樣後續可以恢復老的信號集給線程
printf("sigprocmask(SIG_BLOCK)失敗!\n");
exit(1);
}
if(sigismember(&oldmask,SIGQUIT)) //測試一個指定的信號位是否被置位(爲1),測試的是newmask
{
printf("舊SIGQUIT信號被屏蔽了!\n");
}
else
{
printf("舊SIGQUIT信號沒有被屏蔽!!!!!!\n");
}
printf("我再次要開始休息10秒了--------begin--,此時我無法接收SIGQUIT信號!\n");
sleep(10); //設置阻塞SIGQUIT,無法收到SIGQUIT信號;
printf("我再次已經休息了10秒了--------end----!\n");
if(sigismember(&newmask,SIGQUIT)) //測試一個指定的信號位是否被置位(爲1),測試的是newmask
{
printf("SIGQUIT信號被屏蔽了!\n");
}
else
{
printf("SIGQUIT信號沒有被屏蔽!!!!!!\n");
}
if(sigismember(&newmask,SIGHUP)) //測試另外一個指定的信號位是否被置位,測試的是newmask
{
printf("SIGHUP信號被屏蔽了!\n");
}
else
{
printf("SIGHUP信號沒有被屏蔽!!!!!!\n");
}
sigpending(&pendmask); //檢查信號是懸而未決的
if(sigismember(&pendmask,SIGQUIT)) //SIGQUIT 是懸而未決的。所謂懸而未決,是指SIGQUIT被阻塞還沒有被處理
printf("SIGQUIT pending\n");
//把信號集還原回去,之前被阻塞住的信號會再次得到處理,但是就算之前捕獲了多次也只會觸發一次信號處理函數
if(sigprocmask(SIG_SETMASK,&oldmask,NULL) < 0) //第一個參數用了SIGSETMASK表明設置進程新的信號屏蔽字爲第二個參數指向的信號集,第三個參數沒用
{
printf("sigprocmask(SIG_SETMASK)失敗!\n");
exit(1);
}
printf("sigprocmask(SIG_SETMASK)成功!\n");
if(sigismember(&oldmask,SIGQUIT)) //測試一個指定的信號位是否被置位,這裏測試的當然是oldmask
{
printf("SIGQUIT信號被屏蔽了!\n");
}
else
{
printf("SIGQUIT信號沒有被屏蔽,您可以發送SIGQUIT信號了,我要sleep(10)秒鐘!!!!!!\n");
int mysl = sleep(10);
if(mysl > 0)
{
printf("sleep還沒睡夠,剩餘%d秒\n",mysl);
}
}
printf("end main!\n");
return 0;
}