ITPub博客

首页 > 应用开发 > IT综合 > 【原创】setjmp 和 longjmp 用于信号处理的研究

【原创】setjmp 和 longjmp 用于信号处理的研究

原创 IT综合 作者:oract 时间:2007-10-26 18:33:26 0 删除 编辑

对于那些在执行完信号处理函数之后自动重启系统调用的应用平台例如FreeBSD 6.2 等来说可以用 setjmp 和 longjmp 这一对函数来实现程序的中止。

例如:

[@more@]

#include
#include
#include
#include

static void sig_alrm(int);
static jmp_buf env_alrm;

int main()
{
int n=-10;
char line[1024];

if(signal(SIGALRM,sig_alrm)==SIG_ERR)
{
printf("nError in signal!n");
fflush(stdout);
return 1;
}
if(setjmp(env_alrm)!=0)
{
printf("nError in jump!n");
fflush(stdout);
return 1;
}

alarm(10);
if((n=read(STDIN_FILENO,line,1024))<0)
{
printf("nError in read! n=%dn",&n);
fflush(stdout);
return 1;
}
alarm(0);

write(STDOUT_FILENO,line,n);
return 0;
}

static void sig_alrm(int signo)
{
longjmp(env_alrm,1);
}



执行结果如下:

$ gcc ./chaoshi.c -o ./chaoshi
$ ./chaoshi

Error in jump! ---------------10 秒后输出
$

原因我大概清楚了,是由于longjmp 之后返回到main中去执行
if(setjmp(env_alrm)!=0)
{
printf("nError in jump!n");
fflush(stdout);
return 1;
}
这段代码导致的,由于是longjmp返回额的所以返回值!=0,所以这样曲线实现了进程的中止。

但是对于set 和 jmp 我不知道一旦在jmp回来之后难道仅仅是恢复buf中的栈变量吗?
进程的fd表中所打开的那些fd是否在jmp回来之后仍旧保留着呢??

事实证明fd还是保留着的:


#include
#include
#include
#include
#include
#include

static void sig_alrm(int);
static jmp_buf env_alrm;

int main()
{
int n=-10,fd;
char line[1024];
char ttt[]="1234";

if(signal(SIGALRM,sig_alrm)==SIG_ERR)
{
printf("nError in signal!n");
fflush(stdout);
return 1;
}

if(setjmp(env_alrm)!=0)
{
if(write(fd,ttt,4)!=4)
{
printf("nError in write file!n");
fflush(stdout);
return 1;
}
printf("nError in jump!n");
fflush(stdout);
return 1;
}


if((fd=open("./test.txt",O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))<0)
{
printf("nError in open file!n");
fflush(stdout);
return 1;
}


if(write(fd,ttt,4)!=4)
{
printf("nError in write file!n");
fflush(stdout);
return 1;
}
/* if(setjmp(env_alrm)!=0)
{
printf("nError in jump!n");
fflush(stdout);
return 1;
} */

alarm(10);
if((n=scanf("%s",line))<0)
{
printf("nError in read! n=%dn",&n);
fflush(stdout);
return 1;
}
alarm(0);

write(STDOUT_FILENO,line,n);
return 0;
}

static void sig_alrm(int signo)
{
longjmp(env_alrm,1);
}



运行结果:

$
$ gcc ./test.c -o ./test
$ ./test

Error in jump!
$ cat test.txt
12341234$
$

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7437037/viewspace-978695/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2007-12-23

  • 博文量
    37
  • 访问量
    216950