当sigsuspend函数正在使程序suspend时, 如果被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 SIGALRM handler
    if(signal(SIGUSR1,sig_usr) == SIG_ERR){
        //signal error
    }
    if(signal(SIGUSR2,sig_usr) == SIG_ERR){
        //signal error
    }
    if(signal(SIGALRM,sig_usr) == SIG_ERR){
        //signal error
    }

    //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);
    sigaddset(&wait_mask,SIGUSR2);
    sigaddset(&wait_mask,SIGALRM);
    //SIGUSR1, SIGUSR2 and SIGUSR2 are blocked, all signals except those 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
    }
    else{
        printf("sigsuspend returns\n");
    }

    // // after the sigsuspend returns, the signal mask will restore to what is was before the sigsuspend was executed
    // // check the signal mask
    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("\nSIGINT  is being handled and the signal mask is");    //check the siganl mask
}
//SIGUSR1, SIGUSR2 and SIGALRM 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
    if(signo == SIGALRM)
        print_mask("\nSIGALRM is being handled and the signal mask is");    //check the siganl mask

}

代码说明: sigsuspend设置屏蔽了三个不同信号, 分别是SIGUSR1, SIGUSR2SIGALRM

测试过程

make生成可执行文件sigsuspend, 用shell命令./sigsuspend &使可执行文件在后台运行, shell返回结果为
在这里插入图片描述
可以看到, 25661为该进程的进程号, 用kill命令向该进程以此发送SIGUSR1, SIGUSR2, SIGALRM, SIGINT四个信号
在这里插入图片描述
发送完信号后, shell的返回结果如果下:
在这里插入图片描述
可以看到, sigsuspend函数是在处理完被屏蔽的三个信号SIGUSR1, SIGUSR2SIGALRM后才返回的, 所以被sigsuspend函数屏蔽的信号是在sigsuspend返回前被处理的

被屏蔽的三个信号SIGUSR1, SIGUSR2SIGALRM的处理过程中信号屏蔽字会跟着改变, 处理的顺序会不会跟信号的发送顺序有关, 所以我改变信号的发送顺序为SIGALRM, SIGUSR2, SIGUSR1, SIGINT, 得到shell的返回结果如下:
在这里插入图片描述
可以看到, 对于屏蔽的三个信号SIGALRM, SIGUSR2SIGUSR1的处理过程与前一个信号发送顺序返回的的结果一模一样, 所以可以猜测对于屏蔽的三个信号SIGALRM, SIGUSR2SIGUSR1的处理过程是按照一定的顺序的, 会不会跟信号集添加信号的次序有关, 所以我改变信号集的添加顺序为如下

sigaddset(&wait_mask,SIGALRM);
sigaddset(&wait_mask,SIGUSR2);
sigaddset(&wait_mask,SIGUSR1);

再次按顺序SIGUSR1, SIGUSR2, SIGALRM, SIGINT和顺序SIGALRM, SIGUSR2, SIGUSR1, SIGINT两种顺序发送信号, 得到的结果都是:
在这里插入图片描述
可以看到, 信号的处理顺序和之前几次都一模一样, 所以可以推断, 被屏蔽的信号的处理顺序跟信号集添加的顺序和信号的发送顺序都无关, 是按照特定的顺序, 推测可能是跟信号屏蔽字的本身的位图有关

结论

  1. 被sigsuspend函数屏蔽的信号是在sigsuspend返回前被处理的
  2. 被sigsuspend函数屏蔽的信号的处理顺序跟信号集添加的顺序和信号的发送顺序都无关, 是按照特定的顺序, 又已知屏蔽字的定义是typedef unsigned long sigset_t;, 所以推测可能是跟信号屏蔽字的本身的结构(可能是位图)有关, 假设信号屏蔽字中每一位对应一种信号, 屏蔽字中1为屏蔽对应的信号, 0为不屏蔽对应信号, 所以推测被屏蔽的信号的处理过程大概是, 检查屏蔽字中第一个1, 解除屏蔽, 即将屏蔽位置0, 看是否有对应的信号递送, 如果有, 将屏蔽位置1并执行相应的信号处理程序, 处理完又将对应的屏蔽位置0, 接着检查屏蔽字中下一个1, 解除屏蔽检查是否有这个屏蔽位对应的信号递送, 如果有则置1并处理, 处理完又置0, 接着检查屏蔽字中的下一个1, 以此类推, 直到屏蔽字中没有1, 处理结束
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值