《unix环境高级编程》信号——sigsetjmp 函数和 siglongjmp 函数
2014-11-09 17:18
393 查看
前面《异常处理》介绍了两个关于用于非局部跳转的 setjmp 和 longjmp 函数,在信号处理程序中经常调用 longjmp 函数以返回到程序的主循环中,而不是从该处理程序返回。但是调用 longjmp 有一个问题,当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被自动加到进程的信号屏蔽字中。这阻止了后来产生的这种信号中断该信号处理程序。POSIX.1
并没有说明 setjmp 和
longjmp 对信号屏蔽字的作用,而是定义了两个新函数 sigsetjmp 和siglongjmp。在信号处理程序进行非局部转移时应该使用这两个函数。
在 sigsetjmp 中增加了一个参数,如果 savemask 非0,则 sigsetjmp 在 env 中保存进程的当前信号屏蔽字。调用 siglongjmp 时,如果带非0savemask 的 sigsetjmp 调用已经保存了 env,则 siglongjmp 从其中恢复保存的信号屏蔽字。
测试程序:
参考资料:
《UNIX高级环境编程》
并没有说明 setjmp 和
longjmp 对信号屏蔽字的作用,而是定义了两个新函数 sigsetjmp 和siglongjmp。在信号处理程序进行非局部转移时应该使用这两个函数。
在 sigsetjmp 中增加了一个参数,如果 savemask 非0,则 sigsetjmp 在 env 中保存进程的当前信号屏蔽字。调用 siglongjmp 时,如果带非0savemask 的 sigsetjmp 调用已经保存了 env,则 siglongjmp 从其中恢复保存的信号屏蔽字。
#include <setjmp.h> int sigsetjmp(sigjmp_buf env, int savemask); //若直接调用则返回0,若从siglongjmp调用返回则返回非0值。 void siglongjmp(sigjmp_buf env, int val);
测试程序:
#include "pr_mask.h" /* include the function of pr_mask() */ #include <setjmp.h> #include <time.h> static void sig_usr1(int), sig_alrm(int); static sigjmp_buf jmpbuf; static volatile sig_atomic_t canjump; int main(void) { if(signal(SIGUSR1, sig_usr1) == SIG_ERR) err_sys("signal(SIGUSR1) error"); if(signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error"); pr_mask("starting main: "); if(sigsetjmp(jmpbuf, 1)) { pr_mask("ending main: "); exit(0); } canjump = 1; for(;;) pause(); } static void sig_usr1(int signo) { time_t starttime; if(0 == canjump) return; pr_mask("starting sig_usr1: "); alarm(3); starttime = time(NULL); for(; ;) if(time(NULL) > starttime+5) break; pr_mask("finishing sig_usr1: "); canjump = 0; siglongjmp(jmpbuf,1); } static void sig_alrm(int signo) { pr_mask("in sig_alrm: "); }输出结果:
$ ./sigsetjmp & [1] 15206 starting main: $ kill -USR1 15206 starting sig_usr1: $ in sig_alrm: finishing sig_usr1: ending main: [1]+ Done ./sigsetjmp其中打印函数如下:
#ifndef PR_MASK_H #define PR_MASK_H #include "apue.h" #include <errno.h> void pr_mask(const char *str) { sigset_t sigset; int errno_save; errno_save = errno; if(sigprocmask(0, NULL, &sigset) < 0) err_sys("sigprocmask error"); printf("%s\n", str); if(sigismember(&sigset, SIGINT)) printf("SIGINT\t"); if(sigismember(&sigset, SIGQUIT)) printf("SIGQUIT\t"); if(sigismember(&sigset, SIGUSR1)) printf("SIGUSR1\t"); if(sigismember(&sigset, SIGALRM)) printf("SIGALRM\t"); } #endif
参考资料:
《UNIX高级环境编程》
相关文章推荐
- 《unix环境高级编程》信号——sigsetjmp 函数和 siglongjmp 函数
- 用sigsetjmp和siglongjmp 解决从信号处理程序返回后信号仍被屏蔽问题
- 函数 setjmp, longjmp, sigsetjmp, siglongjmp
- 函数setjmp,longjmp和sigsetjmp,siglongjmp
- Linux Signal (8): sigsetjmp和siglongjmp
- sigsetjmp,siglongjmp的使用
- 信号之sigsetjmp和siglongjmp函数
- 《unix环境高级编程》信号——sigaction 函数
- 《unix环境高级编程》信号——sigaction 函数
- alarm,sigsetjmp,siglongjmp
- siglongjmp 和 sigsetjmp 用法
- 《UNIX环境高级编程》笔记--sigsetjmp和siglongjmp函数
- 10.15 信号_sigsetjmp和siglongjmp函数
- sigsetjmp & siglongjmp
- sigsetjmp,siglongjmp的使用
- sigsetjmp,siglongjmp的使用
- linux下C的信号函数(sig开头的那一簇)的实践
- 关于sigsetjmp,siglongjmp注意点 (UDP超时重传应用)
- C中的信号处理和函数setjmp()/longjmp()的用法
- 2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,