Chinaunix首页 | 论坛 | 博客
  • 博客访问: 309973
  • 博文数量: 55
  • 博客积分: 4000
  • 博客等级: 上校
  • 技术积分: 615
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-07 13:47
文章分类
文章存档

2011年(1)

2010年(2)

2009年(14)

2008年(38)

我的朋友

分类: LINUX

2009-04-27 00:35:55

linux中特殊的跳转函数sigsetjmp()和siglongjmp()
如果是在low-0level subroutine中处理中断和错误的时候特别有用
在使用函数的时候,需要先声明一个sigjmp_buf型的变量,用来保存某一位置(时刻)堆栈上下文的信息。

原型:

//直接调用则返回0, 从siglongjmp调用返回则返回非0值.

int sigsetjmp(sigjmp_buf env, int savesigs);

void siglongjmp(sigjmp_buf env, int val);


sigsetjmp会将当前的堆栈上下文保存在变量env中,这个变量会在后面的siglongjmp中用到。但是当调用个sigsetjmp的函数返

回的时候,env变量将会失效;
如果savesigs非零,阻塞的信号集合也会保存在env变量中,当调用siglongjmp的时候,阻塞的信号集也会被恢复。如果

sigsetjmp本身直接返回,则返回值为0;若sigsetjmp在siglongjmp使用env之后返回,则返回值为非零。

其具体用法见下面的例子:

#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
 
static sigjmp_buf jmpbuf;

void sig_fpe(int signo)
{
   siglongjmp(jmpbuf, 1);
}
 
int main(int argc, char *argv[])
{
    signal(SIGFPE, sig_fpe);
     if (sigsetjmp(jmpbuf, 1) == 0)
// try

        {
// {

              int ret = 10 / 0;
// int ret = 10 / 0;


        }
// }

    else
// catch

        {
// {

             printf("catch exception\n");
// printf("catch excetion\n");

        }
// }

}

其结果如下,说明捕捉到了除零的错误信号:

catch exception

结果分析:

分析:在第一次调用sigsetjmp的时候,由于之前没有调用siglongjmp,所以sigsetjmp的返回值为0,故执行int ret = 10 / 0;的操作这时候产生了一个SIGFPE信号,然后会进入SIGFPE信号的handler中。在handler中调用了siglongjmp,恢复了env,这时候会回到保存env之处,继续重新执行if,由于在本次sigsetjmp调用之前已经有siglongjmp恢复了env,故返回值为非零。从而最终打印出捕捉到的异常信息。这个功能其实相当于cpp中的异常捕捉try...catch块。

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