免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2249 | 回复: 0
打印 上一主题 下一主题

APUE学习笔记之:sigsetjmp和siglongjmp函数 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-12-27 20:12 |只看该作者 |倒序浏览

                                                                                1.在信号处理程序中进行非局部跳转时,应该的使用的两个函数(信号处理程序中不要使用setjmp 和 longjmp函数)。(有关这四个函数:setjmp,longjmp 和 sigsetjmp,siglongjmp 的参数含义、它们如何返回和如何跳转,以及其他信号相关函数,请参看其他资料)
               
               
                #include setjmp.h>
int sigsetjmp(sigjmp_buf env, int savemask);
                      返回值:若直接调用返回0,若从siglongjmp调用返回则返回非0值
void siglongjmp(sigjmp_buf env, int val);
     说明:这两个函数需要配合使用。如果 savemask 非0, 则sigsetjmp 在 env 中保存进程的当前信号屏蔽字。调用siglongjmp时,如果前面步骤中的sigsetjmp 函数的savemask非0,则siglongjmp 函数恢复保存的信号屏蔽字。
2.实例代码
   下面的程序演示了在信号处理程序被调用时,系统所设置的信号屏蔽字如何自动地包括刚被捕捉到的信号。该程序也通过实例说明了如何使用 sigsetjmp 和 siglongjmp 函数。
               
                #include stdio.h>
#include stdlib.h>
#include signal.h>
#include setjmp.h>
#include time.h>
static void                         sig_usr1(int), sig_alrm(int);
static sigjmp_buf                   jmpbuf;
static volatile sig_atomic_t        canjump;
#include errno.h>
void pr_mask(const char *str)
{
        sigset_t    sigset;
        int         errno_save;
        errno_save = errno;     /* we can be called by signal handlers */
        if (sigprocmask(0, NULL, &sigset)  0)
                perror("sigprocmask error");
        printf("%s", str);
        if (sigismember(&sigset, SIGINT))   printf("SIGINT ");
        if (sigismember(&sigset, SIGQUIT))  printf("SIGQUIT ");
        if (sigismember(&sigset, SIGUSR1))  printf("SIGUSR1 ");
        if (sigismember(&sigset, SIGALRM))  printf("SIGALRM ");
        /* remaining signals can go here */
        /* 为了节省空间,这里没有对所有信号进行测试 */
        printf("\n");
        errno = errno_save;
}
int main(void)
{
        if (signal(SIGUSR1, sig_usr1) == SIG_ERR)
                perror("signal(SIGUSR1) error");
        if (signal(SIGALRM, sig_alrm) == SIG_ERR)
                perror("signal(SIGALRM) error");
        pr_mask("starting main: ");
        if (sigsetjmp(jmpbuf, 1)) {
                pr_mask("ending main: ");
                exit(0);
        }
        canjump = 1;         /* now sigsetjmp() is OK */
        for ( ; ; )
                pause();
}
time_t  starttime;
static void sig_usr1(int signo)
{
        if (canjump == 0)
                return;     /* unexpected signal, ignore */
        pr_mask("starting sig_usr1: ");
        alarm(3);               /* SIGALRM in 3 seconds */
        starttime = time(NULL);
        for ( ; ; )             /* busy wait for 5 seconds */
                if (time(NULL) > starttime + 5)
                        break;
        printf("in sig_usr1, interval = %d\n", time(NULL) - starttime);
        pr_mask("finishing sig_usr1: ");
        canjump = 0;
        siglongjmp(jmpbuf, 1);  /* jump back to main, don't return */
}
static void sig_alrm(int signo)
{
        pr_mask("in sig_alrm: ");
        printf("in sig_alrm, interval = %d\n", time(NULL) - starttime);
}
编译后执行结果:
[liumin@localhost sigsetjmp]$ ./m &
[1] 18018
[liumin@localhost sigsetjmp]$ starting main:
[liumin@localhost sigsetjmp]$ kill -SIGUSR1 18018
[liumin@localhost sigsetjmp]$ starting sig_usr1: SIGUSR1
in sig_alrm: SIGUSR1 SIGALRM
in sig_alrm, interval = 3
in sig_usr1, interval = 6
finishing sig_usr1: SIGUSR1
ending main:
[1]+  Done                    ./m
[liumin@localhost sigsetjmp]$
    此程序演示了另一种技术,只要在信号处理程序中调用siglongjmp,就应使用这种技术。仅在调用 sigsetjmp 之后才将变量 canjump 设置为非0值。在信号处理程序中检测此变量,仅当它为非0值时才调用siglongjmp。这提供了一种保护机制,使得在jmpbuf尚未由sigsetjmp 初始化时,防止调用信号处理程序。另外,在本程序中,调用siglongjmp之后程序很快就结束,但是在较大的程序中,在调用siglongjmp 之后的一段较长时间内,信号处理程序可能仍旧被设置,通过检测canjump,就可以起到保护作用。
    在一般的 C 代码中(不是信号处理程序),对于longjmp并不需要这种保护措施。但是,因为信号可能在任何时候发生,所以在信号处理程序中,需要这种保护措施。
    在程序中使用了数据类型 sig_atomic_t,这是由 ISO C 标准定义的变量类型,在写这种类型的变量时不会被中断。它意味着在具有虚拟存储器的系统上这种变量不会跨越页边界,可以用一条机器指令对其进行访问。这种类型的变量总是包括 ISO 类型修饰符 volatile,其原因是:该变量将由两个不同的控制线程--main 函数和异步执行的信号处理程序访问。
               
               
               
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/105349/showart_2132220.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP