Chinaunix首页 | 论坛 | 博客
  • 博客访问: 558894
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: C/C++

2014-08-28 17:14:50

函数原型:
    #include
    int sigsetjmp(sigjmp_buf env, int saveflags)
   void siglongjmp(sigjmp_buf env, int val);

   sigsetjmp/siglongjmp与setjmp/longjmp基本功能是一致的,主要区别是:
   当捕捉到一个信号,并进入信号处理函数时,此时当前信号被自动地加到进程的信号屏蔽字中。这阻止了后来产生的这种信号又中断该信号处理程序。如果用longjmp跳出信号处理程序,那么,对此进程的信号屏蔽字会发生什么呢?
不同的系统处理是不一样的,FreeBSD和Mac OS X会恢复信号屏蔽字,而linux一般不会恢复。
sigsetjmp增加了一个参数savemask,如果savemask不等于0,则sigsetjmp在env中保存进程的当前信号屏蔽字。调用siglongjmp时,如果带非0savemask的sigsetjmp调用已经保存了env,则siglongjmp从其中恢复保存的信号屏蔽字。
一、linux下使用setjmp和longjmp

点击(此处)折叠或打开

  1. #include <signal.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <setjmp.h>
  6. #include <errno.h>
  7. static void sig_usr1(int),sig_alrm(int);
  8. static jmp_buf env;
  9. static volatile sig_atomic_t canjump;

  10. void proc_mask(const char*str)
  11. {
  12.     sigset_t sigset;
  13.     int errno_save;

  14.     errno_save = errno;

  15.     if(sigprocmask(0,NULL,&sigset) < 0)
  16.         perror("sigprocmask error");

  17.     printf("%s",str);

  18.     if(sigismember(&sigset,SIGINT)) printf("SIGINT ");
  19.     if(sigismember(&sigset,SIGQUIT)) printf("SIGQUIT ");
  20.     if(sigismember(&sigset,SIGALRM)) printf("SIGALRM ");
  21.     if(sigismember(&sigset,SIGUSR1)) printf("SIGUSR1 ");

  22.     printf("\n");
  23.     
  24.     errno = errno_save;

  25. }


  26. int main(void)
  27. {
  28.     if(signal(SIGUSR1, sig_usr1) < 0)
  29.         perror("signal(SIGUSR1) error");
  30.     if(signal(SIGALRM, sig_alrm) < 0)
  31.         perror("signal(SIGALRM) error");

  32.     proc_mask("starting main: ");

  33.     if(setjmp(env)) {
  34.         proc_mask("backing to main:");
  35.         return 0;
  36.     }
  37.     
  38.     canjump = 1;
  39.     for(;;)
  40.         pause();

  41. }

  42. static void sig_usr1(int signo)
  43. {
  44.     time_t starttime;

  45.     if(canjump == 0)
  46.         return;

  47.     proc_mask("starting sig_usr1: ");
  48.     alarm(3);
  49.     starttime = time(NULL);

  50.     for(;;)
  51.     {
  52.         if(time(NULL) > starttime+5)
  53.             break;
  54.     }

  55.     proc_mask("ending sig_usr1: ");
  56.     canjump = 0;
  57.     longjmp(env,1);
  58. }

  59. static void sig_alrm(int signo)
  60. {
  61.     proc_mask("sig_alrm: ");
  62. }
编译运行:
gwwu@hz-dev2.aerohive.com:~/test/signal>gcc -g sigsetjmp.c -o a
gwwu@hz-dev2.aerohive.com:~/test/signal>./a &
[3] 24212
gwwu@hz-dev2.wgw.com:~/test/signal>starting main: 


gwwu@hz-dev2.wgw.com:~/test/signal>kill -USR1 24212
gwwu@hz-dev2.wgw.com:~/test/signal>starting sig_usr1: SIGUSR1 
sig_alrm: SIGALRM SIGUSR1 
ending sig_usr1: SIGUSR1 
backing to main:SIGUSR1 --------------------这里保留了siglongjmp时的信号屏蔽字
[3]+  Done                    ./a
gwwu@hz-dev2.wgw.com:~/test/signal>

一、linux下使用sigsetjmp和siglongjmp

点击(此处)折叠或打开

  1. #include <signal.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <time.h>
  5. #include <setjmp.h>
  6. #include <errno.h>
  7. static void sig_usr1(int),sig_alrm(int);
  8. static sigjmp_buf env;
  9. static volatile sig_atomic_t canjump;

  10. void proc_mask(const char*str)
  11. {
  12.     sigset_t sigset;
  13.     int errno_save;

  14.     errno_save = errno;

  15.     if(sigprocmask(0,NULL,&sigset) < 0)
  16.         perror("sigprocmask error");

  17.     printf("%s",str);

  18.     if(sigismember(&sigset,SIGINT)) printf("SIGINT ");
  19.     if(sigismember(&sigset,SIGQUIT)) printf("SIGQUIT ");
  20.     if(sigismember(&sigset,SIGALRM)) printf("SIGALRM ");
  21.     if(sigismember(&sigset,SIGUSR1)) printf("SIGUSR1 ");

  22.     printf("\n");
  23.     
  24.     errno = errno_save;

  25. }


  26. int main(void)
  27. {
  28.     if(signal(SIGUSR1, sig_usr1) < 0)
  29.         perror("signal(SIGUSR1) error");
  30.     if(signal(SIGALRM, sig_alrm) < 0)
  31.         perror("signal(SIGALRM) error");

  32.     proc_mask("starting main: ");

  33.     if(sigsetjmp(env,1)) {
  34.         proc_mask("backing to main:");
  35.         return 0;
  36.     }
  37.     
  38.     canjump = 1;
  39.     for(;;)
  40.         pause();

  41. }

  42. static void sig_usr1(int signo)
  43. {
  44.     time_t starttime;

  45.     if(canjump == 0)
  46.         return;

  47.     proc_mask("starting sig_usr1: ");
  48.     alarm(3);
  49.     starttime = time(NULL);

  50.     for(;;)
  51.     {
  52.         if(time(NULL) > starttime+5)
  53.             break;
  54.     }

  55.     proc_mask("ending sig_usr1: ");
  56.     canjump = 0;
  57.     siglongjmp(env,1);
  58. }

  59. static void sig_alrm(int signo)
  60. {
  61.     proc_mask("sig_alrm: ");
  62. }
编译运行:
gwwu@hz-dev2.wgw.com:~/test/signal>gcc -g sigsetjmp.c -o a
gwwu@hz-dev2.wgw.com:~/test/signal>./a &
[3] 24264
gwwu@hz-dev2.wgw.com:~/test/signal>starting main: 


gwwu@hz-dev2.wgw.com:~/test/signal>kill -USR1 24264
gwwu@hz-dev2.wgw.com:~/test/signal>starting sig_usr1: SIGUSR1 
sig_alrm: SIGALRM SIGUSR1 
ending sig_usr1: SIGUSR1 
backing to main:------------------------------这里返回了恢复信号处理函数之前main函数中的信号屏蔽字


[3]+  Done                    ./a
gwwu@hz-dev2.aerohive.com:~/test/signal>

阅读(939) | 评论(0) | 转发(0) |
0

上一篇:cvs check in 目录

下一篇:DHCPV6的两种模式

给主人留下些什么吧!~~