Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1753610
  • 博文数量: 335
  • 博客积分: 4690
  • 博客等级: 上校
  • 技术积分: 4341
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-08 21:38
个人简介

无聊之人--除了技术,还是技术,你懂得

文章分类

全部博文(335)

文章存档

2016年(29)

2015年(18)

2014年(7)

2013年(86)

2012年(90)

2011年(105)

分类: C/C++

2012-02-08 20:01:18

  1. #include <sigjmp.h>
  2. int sigsetjmp(sigjmp_buf env,int savemask);
  3. void siglongjmp(sigjmp_buf,env,int val);
  4.  int pause(void)      

pause 使调用进程挂起,直至扑捉到一个信号
sigsetjmp 若直接调用则返回0,否则返回非0
若savemask 非0 ,则在当前进程中保存当前的信号屏蔽字
调用siglongjmp时如果带非0的sigsetjmp调用已经保存了env,ze siglongjmp从其中恢复保存的信号屏蔽字
pr_mask
  1. #include "apue.h"
  2. #include <errno.h>

  3. void pr_mask(const char *str)
  4. {
  5.     sigset_t sigset;
  6.     int errno_save;

  7.     errno_save = errno ; /* we can be called by signal handles */
  8.     if (sigprocmask(0,NULL,&sigset) < 0)
  9.         err_sys("sigprocmask error");
  10.     printf("%s",str);

  11.     if (sigismember(&sigset,SIGINT)) printf("SIGINT");
  12.     if (sigismember(&sigset,SIGQUIT)) printf("SIGQUIT");
  13.     if (sigismember(&sigset,SIGUSR1)) printf("SIGUSR1");
  14.     if (sigismember(&sigset,SIGALRM)) printf("SIGALRM");
  15.     /* remaining signals can go here */
  16.     printf("\n");
  17.     errno = errno_save;
  18. }
c10-14.c
  1. #include "apue.h"
  2. #include <time.h>
  3. #include <setjmp.h>

  4. static void sig_usr1(int),sig_alrm(int);
  5. static sigjmp_buf jmpbuf;
  6. static volatile sig_atomic_t canjump;
  7. int main(void )
  8. {
  9.     if ( signal(SIGUSR1,sig_usr1) == SIG_ERR)
  10.         err_sys("signal(sigusr) error");
  11.     if ( signal(SIGALRM,sig_alrm) == SIG_ERR)
  12.         err_sys("signal(sig_alarm) error");
  13.     pr_mask("starting main ");
  14.     
  15.     if (sigsetjmp(jmpbuf,1)){
  16.         pr_mask("ending main");
  17.         exit(0);
  18.     }
  19.     canjump = 1; /* nwo sigsetjmp() is ok */
  20.     for ( ; ; )
  21.         pause();
  22. }
  23. static void sig_usr1(int signo)
  24. {
  25.     time_t starttime;

  26.     if ( canjump == 0)
  27.         return ; /* unexpected signal ingnore */
  28.     pr_mask("starting sig_usr1");
  29.     alarm(3); /* SIGALARM in 3 seconds */
  30.     starttime = time(NULL);
  31.     for ( ; ; ) /* busy wait for 5 seconds */
  32.         if (time(NULL) > starttime +5 )
  33.         break;
  34.     pr_mask("finishing sig_usr1");
  35.     canjump = 0;
  36.     siglongjmp(jmpbuf,1); /* jump back to main,don't return */
  37. }
  38. static void
  39. sig_alrm(int signo )
  40. {
  41.     pr_mask("in sig_alrm");
  42. }
output of the program :
 ./c10-14 &
[1] 10549
 starting main 
 
kill -usr1 10549 
start  sig_usr1
in sig_alrm
finishing sig_usr1

ending main
 
[1]+  Done                    ./c10-14


PS
main()
signal()
signal()
pr_mask();
sigsetjmp();
pause    ------------------进程挂起
       sig_usr1 delivered
------------------------------>sig_usr1
                               pr_mask();  进程扑捉到该信号后,usr1就出现在信号屏蔽
                               alarm()
                               time()
time()
time()
......sig_alrm delivered ------->
                                                                sig_alrm()
pr_mask()  usr,alrm,同时出现在信号屏蔽字中
return()
                         < -------------------------------------

 pr_mask();
siglongjmp();
<-------------------------------------
sigsetjmp()
pr_mask();  信号屏蔽字恢复到了最初的状态,即无信号被屏蔽
exit()

探究:
细心的读者一定发现我的结果和下面的解释不一致, 可是问题出在哪里呢?书上的理论应该是没有问题,但是,实践是检验真理的唯一标准,难道是apue过时了?
此话言之过早!!!!!!!!!!!!!
  1. #include "apue.h"
  2. /* reliable version of signal() ,using posix signaction()*/
  3. Sigfunc *
  4. signal(int signo,Sigfunc * func)
  5. {
  6.     struct sigaction act,oact;
  7.     
  8.     act.sa_handler = func;
  9.     sigemptyset(&act.sa_mask);
  10.     act.sa_flags = 0;
  11.     if ( signo == SIGALRM){
  12.     #ifdef SA_INTERRUPT
  13.         act.sa_flags |= SA_INTERRUPT;
  14.     #endif
  15.     } else{
  16.     #ifdef SA_RESTART
  17.         act.sa_flags |= SA_RESTART;
  18.     #endif
  19.     }
  20.     if (sigaction(signo,&act,&oact) < 0)
  21.         return(SIG_ERR);
  22.     return(oact.sa_handler);
  23. }
看到这个函数你是不是想起什么来了,原来“有些系统支持旧的不可靠语义signal函数,其目的是实现二进制向后兼容“linux就是这样的例子,它默认的signal函数就是不可靠语义,所以呢,在调用一次信号处理函数后会自动设置成默认处理方式而不会再调用了‘
作者的系统是ubuntu系统
使用该函数编译后,结果就和书上面一致了
至此问题解决,因此告诫自己,看书一定仔细,要多思考
  1. #include <signal.h>
  2. int sigaction(int signo,struct sigaction * act,struct sigaction  * oact);
signo 是要检测或是具体要修改的信号
act非空,则要修改该信号的动作
oact 非空,则系统经由oact指针返回该信号的上一个动作
  1. struct sigaction{
  2. void (*sa_handler)(int); /* addr of signao handler or SIG_IGN or SIG_DFL*/
  3. sigset_t sa_mask;      /* additional  signal to block */
  4. int      sa_flags;       /* signal options,figure 10-16 */


  5. void (*sa_handler)(int,siginfo_t*,void *);
  6. }
当更改信号时,如果sa_handler字段包含了一个信号捕捉函数的地址,则sa_mask说明了一个信号集
在调用该信号捕捉函数之前,这一个信号集要加入到进程的信号屏蔽字中,仅当从信号处理函数返回时再将进程的信号屏蔽字复位为原先值。














阅读(1187) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~