信號sigprocmask函數

 

#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;
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章