由一段代码直观深入理解sigsuspend函数

示例代码及执行结果

void sig_int(int);
void sig_usr(int);

int main(){

    print_mask("at the beginning:");
    
    sigset_t new_mask,old_mask,wait_mask;

    //install signal SIGINT handler
    if(signal(SIGINT,sig_int) == SIG_ERR){
        //signal error
    }
    //install signal SIGUSR1 SIGUSR2 handler
    if(signal(SIGUSR1,sig_usr) == SIG_ERR){
        //signal error
    }
    if(signal(SIGUSR2,sig_usr) == SIG_ERR){
        //signal error
    }

    //block the signal SIGINT
    //protect critical region of code from being interrupted by signal SIGINT
    sigemptyset(&new_mask);
    sigaddset(&new_mask,SIGINT);
    if(sigprocmask(SIG_BLOCK,&new_mask,&old_mask) == -1){
        //sigprocmask error
    }
    print_mask("after block the SIGINT and before the sigsuspend:");

    /*
    critical region of code being protected from being interrupted by signal SIGINT
    */

    //reset signal mask to wait_mask instead of adding wait_mask to original mask and wait for a signal to interrupt it and continue the program
    //test the signal mask before the sigsuspend returns(caught a signal and being exectuted the handler)
    sigemptyset(&wait_mask);
    sigaddset(&wait_mask,SIGUSR1);
    //SIGUSR1 is blocked, all signals except SIGUSR1 are allowed to interrupt the suspend and makes the sigsuspend function return
    //when program is being suspended by function sigsuspend, the signal which is not blocked will be delivered and handled, and the current signal mask includes wait_mask and itself, the sigsuspend will return -1 after the handling
    if(sigsuspend(&wait_mask) != -1){   
        //sigsuspend error
    }

    //after the sigsuspend returns, the signal mask will restore to what is was before the sigsuspend was executed
    //check the signal mask
    print_mask("after sigsuspend:");

    //restore the mask to what it was before the program started and check the result after restoring
    if(sigprocmask(SIG_SETMASK,&old_mask,NULL) == -1){
        //sigprocmask error
    }
    print_mask("at the end:");
    exit(0);
}

//the signal which is being handled by its handler will be added to the signal mask automatically to prevent being interrupted by the same signal

//SIGINT handler
void sig_int(int signo){
    print_mask("\nin sig_int:");    //check the siganl mask
}
//SIGUSR1 handler
void sig_usr(int signo){
    if(signo == SIGUSR1)
        print_mask("\nSIGUSR1 is being handled and the signal mask is");    //check the siganl mask
    if(signo == SIGUSR2)
        print_mask("\nSIGUSR2 is being handled and the signal mask is");    //check the siganl mask
}

make生成执行文件sigsuspend, 执行命令./sigsuspend &让该可执行文件在后台运行, shell返回结果如下
在这里插入图片描述
根据shell返回的进程号24099,执行命令kill -USR2 24099向该进程发送SIGUSR2信号, shell返回结果如下
在这里插入图片描述

执行结果分析

wait_mask只包含了SIGUSR1信号, 所以sigsuspend函数设置signal mask时只屏蔽了SIGUSR1, 其他的信号都会正常响应, 所以在suspend期间, 我们往该进程发送了SIGUSR2信号后, 信号会立即被响应, 执行相应的信号处理程序. 在SIGUSR2的信号处理程序中我们返回了此时进程的信号屏蔽字, 结果是{SIGUSR1 SIGUSR2}, 证实了sigsuspend函数改变了信号屏蔽字使其只包含了SIGUSR1, 而SIGUSR2之所以会出现在信号屏蔽字的原因是在一个信号被处理的过程中(正在执行信号处理程序), 该信号会被加入信号屏蔽字, 即在该信号被处理完成之前, 相同的信号会被屏蔽掉以保证此信号完整的被处理完(信号处理程序被执行完)

结论

  1. sigsuspend函数不是在原来的信号屏蔽字的基础上再屏蔽给定的mask里的信号, sigsuspend会完全按照给定的mask改变信号屏蔽字
  2. 当sigsuspend函数正在使程序suspend时, 没有被sigsuspend屏蔽的信号到达时, 会立刻被响应并执行相应的信号处理程序, 信号处理程序执行的过程中该信号会被加入到信号屏蔽字, 信号处理程序执行完毕后, sigsuspend函数会返回
  3. sigsuspend函数返回后, 信号屏蔽字会恢复到sigsuspend函数执行前的值
  4. 当sigsuspend函数正在使程序suspend时, 如果被sigsuspend函数屏蔽的信号被发送, 这些信号何时被处理, 如果屏蔽的信号有很多种, 而且这些信号都发送了, 这些信号被处理的顺序是怎样的, 请看我的这篇文章当sigsuspend函数正在使程序suspend时, 如果被sigsuspend函数屏蔽的信号被发送, 这些信号何时被处理, 如果屏蔽的信号有很多种, 而且这些信号都发送了, 这些信号被处理的顺序
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值