sigsuspend()函数解决时序竞态问题

sigsuspend解决时序竞态问题

  • 使用pause()函数, 会导致在恢复信号集之前程序挂起
#include <unistd.h>
#include <signal.h>
#include <stdio.h> 

void handler(int sig)    //信号处理函数的实现
{
    printf("SIGINT sig\n");
}

int main(void)
{
    sigset_t new,old;
    struct sigaction act;

    act.sa_handler = handler;  //信号处理函数handler
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGINT, &act, 0);  //准备捕捉SIGINT信号(注册)

    sigemptyset(&new);
    sigaddset(&new, SIGINT);
    sigprocmask(SIG_BLOCK, &new, &old);  //将SIGINT信号阻塞,同时保存当前信号集
    printf("Blocked\n");    //模拟阻塞了SIGINT

    pause(); // 因为之前阻塞了SIGINT, 所以SIGINT在挂起期间永远不会递达, 程序将永久挂起

    sigprocmask(SIG_SETMASK, &old, NULL);  //恢复原阻塞信号集
    printf("sigprocmask recovered\n");

    return 0;

}
  • 使用sigsuspend()函数在程序挂起期间临时撤销对wait信号集中的SIGUSR1以外的信号阻塞(只临时阻塞SIGUSR1), 在挂起期间, 程序可以对除SIGUSR1以外的信号(如SIGINT)进行处理, 执行sigaction
  • sigsuspend实际是将临时阻塞SIGUSR1和pause结合起来原子操作
  • 临时替换信号集wait和挂起是一个原子操作
#include <unistd.h>
#include <signal.h>
#include <stdio.h> 

void handler(int sig)    //信号处理函数的实现
{
    printf("SIGINT sig\n");
}

int main(void)
{
    sigset_t new,old, wait;
    struct sigaction act;

    act.sa_handler = handler;  //信号处理函数handler
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    sigaction(SIGINT, &act, 0);  //准备捕捉SIGINT信号

    sigemptyset(&new);
    sigaddset(&new, SIGINT);

    //sigprocmask作用: 改变当前进程的阻塞信号集
    sigprocmask(SIG_BLOCK, &new, &old);  //将SIGINT信号阻塞(模拟Ctrl+c失效),同时保存当前信号集

    printf("Blocked\n");    // 模拟阻塞SIGINT(Ctrl+c), 模拟失去cpu

    sigemptyset(&wait);
    sigaddset(&wait, SIGUSR1);

    //pause(); 是挂起期间对所有信号都响应

    // 在程序挂起期间对wait(SIGUSR1)临时不响应, 而响应其他所有信号,如SIGINT, 挂起结束后恢复. 
    // 程序挂起期间可以不想被SIGUSR1打断
    // 挂起期间可以用SIGINT(Ctrl+c)唤醒进程
    sigsuspend(&wait);  

    sigprocmask(SIG_SETMASK, &old, NULL);  //恢复原阻塞信号集
    printf("sigprocmask recovered\n");

    return 0;

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值