(2.4)信號編程進階、sigprocmask範例

一:信號集

    //一個進程,必須能夠記住 這個進程 當前阻塞了哪些信號

    //000000000000000000000

    //我們需要 “信號集 ”的這麼一種數據類型(結構),能夠把這60多個信號都表示下(都裝下)。

    //0000000000,0000000000,0000000000,00,0000000000,0000000000,0000000000,00 (64個二進制位)

    //linux 是用sigset_t結構類型來表示信號集的;

    //typedef struct{

    // unsigned long sig[2];

    //}sigset_t

    //信號集的定義:信號集表示一組信號的來(1)或者沒來(0)

    //信號集相關的數據類型: sigset_t;

二:信號相關函數

    //a)sigemtpyset():把信號集中的所有信號都清0,表示這60多個信號都沒有來;

    //00000000000000000000000000.....

    //b)sigfillset();把信號集中的所有信號都設置爲1,跟sigemptyset()正好相反;

    //11111111111111111111111111.....

    //c)用sigaddset(),sigdelset()就可以往信號集中增加信號,或者從信號集中刪除特定信號;

 

    //d)sigprocmask,sigmember

    //一個進程,裏邊會有一個信號集,用來記錄當前屏蔽(阻塞)了哪些信號;

     //如果我們把這個信號集中的某個信號位設置爲1,就表示屏蔽了同類信號,此時再來個同類信號,那麼同類信號會被屏蔽,不能傳遞給進程;

     //如果這個信號集中有很多個信號位都被設置爲1,那麼所有這些被設置爲1的信號都是屬於當前被阻塞的而不能傳遞到該進程的信號;

    //sigprocmask()函數,就能夠設置該進程所對應的信號集中的內容;

三:sigprocmask等信號函數範例演示

//sleep()函數能夠被打斷:

     //(1)時間到達了;

     //(2)來了某個信號,使sleep()提前結束,此時sleep會返回一個值,這個值就是未睡夠的時間;

 

    //sigaction()函數;

 

#include <stdio.h>
#include <stdlib.h>  //malloc
#include <unistd.h>
#include <signal.h>

//信號處理函數
void sig_quit(int signo)
{   
    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; //信號集,新的信號集,原有的信號集,掛起的信號集
    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就是該信號被阻塞掉唄

    //sigprocmask():設置該進程所對應的信號集
    if(sigprocmask(SIG_BLOCK,&newmask,&oldmask) < 0)  //第一個參數用了SIG_BLOCK表明設置 進程 新的信號屏蔽字 爲 “當前信號屏蔽字 和 第二個參數指向的信號集的並集
    {                                                 //一個 ”進程“ 的當前信號屏蔽字,剛開始全部都是0的;所以相當於把當前 "進程"的信號屏蔽字設置成 newmask(屏蔽了SIGQUIT);
                                                      //第三個參數不爲空,則進程老的(調用本sigprocmask()之前的)信號集會保存到第三個參數裏,用於後續,這樣後續可以恢復老的信號集給線程
        printf("sigprocmask(SIG_BLOCK)失敗!\n");
        exit(1);
    }
    printf("我要開始休息10秒了--------begin--,此時我無法接收SIGQUIT信號!\n");
    sleep(10);   //這個期間無法收到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");
    }

    //現在我要取消對SIGQUIT信號的屏蔽(阻塞)--把信號集還原回去
    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("再見了!\n");
    return 0;
}

 

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