【博客140】Linux信号处理——解除信号阻塞需注意的问题

内容: 记录一个解除信号阻塞时一个有趣的问题
测试代码:设置信号阻塞之后,看收到此信号后未决状态集的状态,然后再解除阻塞看会发生什么?

#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
  
void handler(int num)
{
    if(num == SIGINT){
        cout << "recv the SIGINT" << endl;
    }
    else if (num == SIGQUIT){
        sigset_t unblock_set;
        sigemptyset(&unblock_set);
        sigaddset(&unblock_set, SIGINT);
        sigprocmask(SIG_UNBLOCK, &unblock_set, NULL);
    }
}

void print_pending(sigset_t * pset)
{
    int i = 0;
    cout << "未决状态字(64位):";
    for (i = 1; i <= 64; ++i){
        if(sigismember(pset, i))
            cout << 1;
        else
            cout << 0;
        if(i % 8 == 0){
            cout << " ";
        }
    }
    cout << endl;
}

int main()
{
    sigset_t block_set;
    sigset_t print_set;  
    sigemptyset(&block_set);
    sigaddset(&block_set, SIGINT);
    sigprocmask(SIG_BLOCK, &block_set, NULL);
    signal(SIGINT, handler);
    signal(SIGQUIT, handler);

    while(1){        
        sigpending(&print_set);
        print_pending(&print_set);       
        sleep(1);
    }

    return 0;
}

运行结果分析:
1.刚开始,设置了阻塞,但是没有发送信号,所以未决集合为空

在这里插入图片描述
2.ctrl+c发送信号后,未决信号集显示有信号未决
在这里插入图片描述
3.ctrl+\解除信号集后看到阻塞的信号送达,信号处理函数调用
在这里插入图片描述
这一切貌似很正常对吧,但是你再发送一次ctrl+c看看发生了什么?在这里插入图片描述
你会发现又阻塞了,这是为什么?刚不是解除阻塞了吗?而且也没有再设置阻塞呀?

原因:如果在信号处理函数中对某个信号进行解除阻塞时,则只是将pending位清0,让此信号递达一次,但不会将block位清0,即再次产生此信号时还是会被阻塞,处于未决状态。如果你在main函数解除一下阻塞发现是真的把block位给清0了

测试代码如下:我们设置10秒后main函数while中会解除阻塞

#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;
  
void handler(int num)
{
    if(num == SIGINT){
        cout << "recv the SIGINT" << endl;
    }
    else if (num == SIGQUIT){
        sigset_t unblock_set;
        sigemptyset(&unblock_set);
        sigaddset(&unblock_set, SIGINT);
        sigprocmask(SIG_UNBLOCK, &unblock_set, NULL);
    }
}

void print_pending(sigset_t * pset)
{
    int i = 0;
    cout << "未决状态字(64位):";
    for (i = 1; i <= 64; ++i){
        if(sigismember(pset, i))
            cout << 1;
        else
            cout << 0;
        if(i % 8 == 0){
            cout << " ";
        }
    }
    cout << endl;
}

int main()
{
    int i = 0;
    sigset_t block_set;
    sigset_t print_set;  
    sigemptyset(&block_set);
    sigaddset(&block_set, SIGINT);
    sigprocmask(SIG_BLOCK, &block_set, NULL);
    signal(SIGINT, handler);
    signal(SIGQUIT, handler);

    while(1){        
        i++;
        sigpending(&print_set);
        print_pending(&print_set);       
        sleep(1);
  
        if (i >19 && i<21)
        {
        sigset_t unblock_set;
        sigemptyset(&unblock_set);
        sigaddset(&unblock_set, SIGINT);
        sigprocmask(SIG_UNBLOCK, &unblock_set, NULL);
        }

    }
    return 0;
}

运行结果:观察到10s后解除阻塞,再收到ctrl+c已经不再阻塞,未决信号集一直为0
在这里插入图片描述
总结:即如果在信号处理函数中对某个信号进行解除阻塞时,则只是将pending位清0,让此信号递达一次,但不会将block位清0,即再次产生此信号时还是会被阻塞,处于未决状态。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值