[Linux]返回被阻塞的信号集

一、概述

另一篇实例说到,进程可以屏蔽它不想接收的信号集。

事实上这些被屏蔽的信号只是阻塞在内核的进程表中,因为他们不能递送给进程,所以状态是未决的(pending)。

利用sigpending函数可以返回这些未决信号集。

int sigpending(sigset_t *set);

二、示例

1.示例中进程屏蔽了SIGUSR1信号,当给进程发送该信号后,它就会被sigpending函数返回,可以尝试先向进程发送SIGUSR2,然后再发送SIGUSR1,再而发送SIGUSR2,观察信号处理函数的变化。

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

void sig_usr(int signo)
{
    sigset_t s_2;
    if (signo == SIGUSR1)
        printf("received SIGUSR1
");
    else if (signo == SIGUSR2)
        printf("received SIGUSR2
");
    else
        printf("received signal %d
", signo);
    sigpending(&s_2);
    if(sigismember(&s_2, SIGUSR1))
        printf("SIGUSR1 pending
");
}


int main(void){
    sigset_t s_1;
    sigemptyset(&s_1);
    sigaddset(&s_1, SIGUSR1);
    sigprocmask(SIG_SETMASK, &s_1, NULL);

    signal(SIGUSR1, sig_usr);
    signal(SIGUSR2, sig_usr);

    for (;;)
    {
        pause();
    }
    return 0;
}

 2.现在来修改一下示例1,把信号处理函数改为,当检测到有SIGUSR1被阻塞时,马上释放它(再次调用屏蔽字函数,把信号集设为空集)

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

void sig_usr(int signo)
{
    sigset_t s_2, s_3;
    if (signo == SIGUSR1)
        printf("received SIGUSR1
");
    else if (signo == SIGUSR2)
        printf("received SIGUSR2
");
    else
        printf("received signal %d
", signo);
    sigpending(&s_2);
    if(sigismember(&s_2, SIGUSR1)){
        printf("SIGUSR1 pending, now release it
");
        sigemptyset(&s_3);
        sigprocmask(SIG_SETMASK, &s_3, NULL);
    }
}


int main(void){
    sigset_t s_1;
    sigemptyset(&s_1);
    sigaddset(&s_1, SIGUSR1);
    sigprocmask(SIG_SETMASK, &s_1, NULL);

    signal(SIGUSR1, sig_usr);
    signal(SIGUSR2, sig_usr);

    for (;;)
    {
        pause();
    }
    return 0;
}

测试时,先发送两次SIGUSR1信号,然后发送一次SIGUSR2信号,输出结果是:

received SIGUSR2
SIGUSR1 pending, now release it
received SIGUSR1

可见:

1.信号被释放后进程马上接收到了该信号。

2.尽管已向进程发送了多次SIGUSR1,但是最后的释放,进程只收到一次SIGUSR1信号,这是因为有些信号是不被列队的,如果阻塞该信号,那么尽管发送了多次,最后释放时也只会收到一次,请参考《Unix高级环境编程》第10.13章。

原文地址:https://www.cnblogs.com/yiyide266/p/10654009.html