sigjmp longjmp 和 sigsetjmp siglongjmp比较

阅读《Unix环境高级编程》P283页  10.15处的体会。(错误之处,望大家批评指正)

本文通过几个实验说明sigjmp  longjmp 和 sigsetjmp  siglongjmp的区别。

实验一:执行信号X(任意信号)处理程序时,X信号会被自动加入到信号屏蔽字。信号处理程序执行完毕,信号屏蔽字会恢复原来的。

    1 #include <stdio.h>                                                                                                                              
    2 #include "apue.h"
    3 #include <signal.h>
    4 #include <setjmp.h>
    5 
    6 
    7 void deal_sig(int a)
    8 {
    9     sigset_t sigpend;
   10     sigset_t sigmask;
   11     sleep(5);//延时等待SIGQUIT再次发生
   12     sigpending(&sigpend);
   13     sigprocmask(0,NULL,&sigmask);
   14 
   15     if(sigismember(&sigpend,SIGQUIT))
   16     {
   17         printf("SIGQUIT is pending\n");
   18     }
   19     else
   20     {
   21         printf("SIGQUIT is not pending\n");
   22     }
   23 
   24     if(sigismember(&sigmask,SIGQUIT))
   25     {
   26         printf("SIGQUIT is in sigmask\n");
   27     }
   28     else
   29     {
   30         printf("SIGQUIT is not in sigmask\n");
   31     }
   32 
   33 }
   34 
   35 int main()
   36 {
   37     int sleep_ret;
   38     sigset_t sigmask;
   39     if(signal(SIGQUIT,deal_sig)==SIG_ERR)
   40     {
   41         printf("signal error\n");
   42         exit(1);
   43     }
   44     sleep_ret = sleep(5);//延时等待信号发生
   45 
   46 
   47     sigprocmask(0,NULL,&sigmask);
   48     if(sigismember(&sigmask,SIGQUIT))
   49     {
   50         printf("main : SIGQUIT is in sigmask\n");
   51     }
   52     else
   53     {
   54         printf("main : SIGQUIT is not in sigmask\n");
   55     }
   56 
   57     printf("sleep_ret = %d\n",sleep_ret);
   58     exit(0);
   59 }

运行结果

^\^\SIGQUIT is pending
SIGQUIT is in sigmask
SIGQUIT is not pending
SIGQUIT is in sigmask
main : SIGQUIT is not in sigmask
sleep_ret = 4

第一SIGQUIT信号发生时,正在执行信号处理程序,此时再次发生该信号,信号处于未决态,信号被自动加入信号屏蔽字。

信号处理程序执行完,第二次的信号开始处理,信号又被加入信号屏蔽字,但是没有第三次发生SIGQUIT,因此没有SIGQUIT在未决态。

main:是主函数打印的,信号处理程序返回,检查信号屏蔽字,发现,SIGQUIT不在信号屏蔽字。(证明信号处理程序返回,自动恢复了信号屏蔽字。)

信号处理程序返回,sleep不会继续睡眠,直接返回剩余的时间,因此sleep_ret=4。

实验二:如果用longjmp跳出信号处理程序,进程的信号屏蔽字会发生什么。不同平台处理方式不同。

Linux3.2.0和Solaris不会恢复信号屏蔽字,FreeBSD8.0,MacOS X 10.6.8会保存和恢复信号屏蔽字。

测试环境Ubantu

    1 #include <stdio.h>                                                                                                                              
    2 #include "apue.h"
    3 #include <signal.h>
    4 #include <setjmp.h>
    5 
    6 static jmp_buf jmpbuf;
    7 
    8 void deal_sig(int a)
    9 {
   10     sigset_t sigpend;
   11     sigset_t sigmask;
   12     sleep(5);
   13     sigpending(&sigpend);
   14     sigprocmask(0,NULL,&sigmask);
   15      
   16     if(sigismember(&sigpend,SIGQUIT))
   17     {
   18         printf("SIGQUIT is pending\n");
   19     }
   20     else
   21     {
   22         printf("SIGQUIT is not pending\n");
   23     }
   24 
   25     if(sigismember(&sigmask,SIGQUIT))
   26     {
   27         printf("SIGQUIT is in sigmask\n");
   28     }
   29     else
   30     {
   31         printf("SIGQUIT is not in sigmask\n");
   32     }
   33     longjmp(jmpbuf,1);
   34 }
   35 
   36 int main()
   37 {
   38     sigset_t sigmask;
   39     sigset_t sigpend;
   40     if(signal(SIGQUIT,deal_sig)==SIG_ERR)
   41     {
   42         printf("signal error\n");
   43         exit(1);
   44     }
   45     while(setjmp(jmpbuf)==0);
   46 
   47     sigprocmask(0,NULL,&sigmask);
   48     if(sigismember(&sigmask,SIGQUIT))
   49     {
   50         printf("main : SIGQUIT is in sigmask\n");
   51     }
   52     else
   53     {
   54         printf("main : SIGQUIT is not in sigmask\n");
   55     }
   56     sigpending(&sigpend);
   57     if(sigismember(&sigpend,SIGQUIT))
   58     {
   59         printf("main : SIGQUIT is pending\n");
   60     }
   61     else
   62     {
   63         printf("main : SIGQUIT is not pending\n");
   64     }
   65 
   66     exit(0);
   67 }

运行结果

^\^\SIGQUIT is pending
SIGQUIT is in sigmask
main : SIGQUIT is in sigmask
main : SIGQUIT is pending

第一次发生信号,进入信号处理程序,SIGQUIT自动加入信号屏蔽字,第二次发生的信号处于未决态。

信号处理程序返回,SIGQUIT还在屏蔽字中,第二次发生的信号还是未决态。

实验三:实验二的sigjmp  longjmp 换成 sigsetjmp  siglongjmp

    1 #include <stdio.h>
    2 #include "apue.h"                                                                                                                               
    3 #include <signal.h>
    4 #include <setjmp.h>
    5 
    6 static jmp_buf jmpbuf;
    7 
    8 void deal_sig(int a)
    9 {
   10     sigset_t sigpend;
   11     sigset_t sigmask;
   12     sleep(5);
   13     sigpending(&sigpend);
   14     sigprocmask(0,NULL,&sigmask);
   15 
   16     if(sigismember(&sigpend,SIGQUIT))
   17     {
   18         printf("SIGQUIT is pending\n");
   19     }
   20     else
   21     {
   22         printf("SIGQUIT is not pending\n");
   23     }
   24 
   25     if(sigismember(&sigmask,SIGQUIT))
   26     {
   27         printf("SIGQUIT is in sigmask\n");
   28     }
   29     else
   30     {
   31         printf("SIGQUIT is not in sigmask\n");
   32     }
   33     siglongjmp(jmpbuf,1);
   34 }
   35 
   36 int main()
   37 {
   38     sigset_t sigmask;
   39     sigset_t sigpend;
   40     if(signal(SIGQUIT,deal_sig)==SIG_ERR)
   41     {
   42         printf("signal error\n");
   43         exit(1);
   44     }
   45     while(sigsetjmp(jmpbuf,1)==0);
   46 
   47     sigprocmask(0,NULL,&sigmask);
   48     if(sigismember(&sigmask,SIGQUIT))
   49     {
   50         printf("main : SIGQUIT is in sigmask\n");
   51     }
   52     else
   53     {
   54         printf("main : SIGQUIT is not in sigmask\n");
   55     }
   56     sigpending(&sigpend);
   57     if(sigismember(&sigpend,SIGQUIT))
   58     {
   59         printf("main : SIGQUIT is pending\n");
   60     }
   61     else
   62     {
   63         printf("main : SIGQUIT is not pending\n");
   64     }
   65 
   66     exit(0);
   67 }

运行结果1:sigsetjmp(jmpbuf,1)自动恢复了信号屏蔽字。

^\^\SIGQUIT is pending
SIGQUIT is in sigmask
SIGQUIT is not pending
SIGQUIT is in sigmask
main : SIGQUIT is not in sigmask
main : SIGQUIT is not pending

运行结果2:sigsetjmp(jmpbuf,0)第二个参数填0,没有自动恢复信号屏蔽字。(非零会恢复)

^\^\SIGQUIT is pending
SIGQUIT is in sigmask
main : SIGQUIT is in sigmask
main : SIGQUIT is pending

总结:sigjmp  longjmp 和 sigsetjmp  siglongjmp比较

1、信号处理程序正常结束,会恢复原来的信号屏蔽字。

2、在Linux3.2.0中,longjmp跳出信号处理程序,不会恢复原来的信号屏蔽字。

3、siglongjmp的第二个参数非零,恢复信号屏蔽字,为0则不恢复。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值