Linux 等待信号(sigsuspend)

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

/*
设计说明:
    设计期望,在 pause() 之后,收到 SIGINT 信号可以结束程序。
    场景一: 当信号在第二步之前到来,第三步取消信号阻塞,此时会执行信号注册函数,信号直接处理完成了,然后回到主流程中,程序会在第四步(pause)这边阻塞。
    场景二: 当信号在第二步与第三步之间到来,第三步取消信号阻塞,此时会执行信号注册函数,信号直接处理完成了,然后回到主流程中,程序会在第四步(pause)这边阻塞。
    场景三: 当信号在第三步与第四步之间到来,第三步取消信号阻塞,此时会执行信号注册函数,信号直接处理完成了,然后回到主流程中,程序会在第四步(pause)这边阻塞。
    场景四: 当信号在第四步之后到来,此时收到 SIGINT 信号,会打断 pause ,执行信号注册函数,程序结束
*/

void test()
{
    sigset_t set;

    //1.设置需要处理的信号
    sigemptyset(&set);
    sigaddset(&set, SIGINT);

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

    // 3.取消信号阻塞
    sigprocmask(SIG_UNBLOCK, &set, NULL);

    // 4.函数结束
    pause();

}

int main()
{
    test();
    return 0;
}

 为了上述问题,需要在一个原子操作中先恢复信号屏蔽字,然后使进程休眠。这种功能是由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返回,进程恢复执行。

*/

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

 

posted on 2019-12-16 19:56  寒魔影  阅读(3130)  评论(0编辑  收藏  举报

导航