Linux 等待信號(sigsuspend)


/* sigsuspend()函數說明 */

#include <stdio.h>
#include <signal.h>

/*
知識補充:
    sigsuspend()函數

    函數原型:
    #include <signal.h>
    int sigsuspend(const sigset_t *mask);

    參數說明:
    @mask 希望屏蔽的信號

    返回值:
    sigsuspend返回后將恢復調用之前的的信號掩碼。信號處理函數完成后,進程將繼續執行。該系統調用始終返回-1,並將errno設置為EINTR.

    備注:
    進程執行到sigsuspend時,sigsuspend並不會立刻返回,進程處於TASK_INTERRUPTIBLE狀態並立刻放棄CPU,
    等待UNBLOCK(mask之外的)信號的喚醒。進程在接收到UNBLOCK(mask之外)信號后,調用處理函數,然后還原信號集,
    sigsuspend返回,進程恢復執行。

    使用場景:
    sigsuspend() 函數可以更改進程的信號屏蔽字可以阻塞所選擇的信號,或解除對它們的阻塞。
    使用這種技術可以保護不希望由信號中斷的代碼臨界區。
    如果希望對一個信號解除阻塞,然后pause等待以前被阻塞的信號發生,那么必須使用 sigsuspend() 函數
    pause() 函數無法達成上述目的

    //a.阻塞信號
    if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
        err_sys("SIG_BLOCK error");

    //b.解除阻塞
    if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
        err_sys("SIG_SETMASK error");

    //c.等待信號
    pause();    

    說明: 如果在等待信號階段,發送信號給程序,那么 pause()函數退出,處理信號
        如果在解除阻塞之前發送信號,信號一被解除,立馬執行信號處理函數,執行完畢后,回來執行 pause()函數,程序被卡住

        為了糾正此問題,需要在一個原子操作中先恢復信號屏蔽字,然后使進程休眠。這種功能是由 sigsuspend() 函數提供的。

*/

void test()
{
    sigset_t set;

    //1.設置需要處理的信號
    sigemptyset(&set);
    sigaddset(&set, SIGCHLD);
    sigaddset(&set, SIGALRM);
    sigaddset(&set, SIGIO);
    sigaddset(&set, SIGINT);

    //2.先屏蔽這些信號
    if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) 
    {
        printf("sigprocmask() failed .\n");
        return;
    }

    //3.做一些初始化操作

    //4.開始接收這些信號
    sigemptyset(&set);    //清空信號集

    sigsuspend(&set);    //等待信號過來處理

}

int main()
{
    test();
    printf("-----ok-------\n");
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM