setjmp 及 alarm实现带超时限制调用read
2015-05-25 11:34
477 查看
setjmp和longjmp函数--非局部跳转语句。
非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。
#include <setjmp.h>
Int setjmp(jmp_buf env); 返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
应用:
当检查到一个错误时,则以两个参数调用longjmp函数,第一个就是在调用setjmp时所用的env,第二个参数是具有非0值的val,它将成为从setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp。
注: longjmp必须在setjmp调用之后,而且longjmp必须在setjmp的作用域之内。具体来说,在一个函数中使用setjmp来初始化一个全局标号,然后只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到 setjmp的下一条语句执行。实际上setjmp函数将发生调用处的局部环境保存在了一个jmp_buf的结构当中,只要主调函数中对应的内存未曾释放
(函数返回时局部内存就失效了),那么在调用longjmp的时候就可以根据已保存的jmp_buf参数恢复到setjmp的地方执行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h> //signal
#include <unistd.h> //alarm
#include <setjmp.h> //setjmp and longjmp
#define MAXBUFFLEN 1024
/*
*使用longjmp 及 alarm实现带超时限制调用read
*/
static void sig_alrm(int signo);//声明alarm信号处理函数
static jmp_buf env_alrm;
int main(int argc, char *argv[])
{
int n;
char buf[MAXBUFFLEN];
memset(buf, 0x00, sizeof(buf));
if(signal(SIGALRM, sig_alrm) == SIG_ERR){
printf("signal(SIGALRM) Error\n");
exit(-1);
}
//第一次调用setjmp会返回0,当longjmp被调用后,代码会跳转到setjmp处执行,setjmp将会返回longjmp设置的值。
if(setjmp(env_alrm) != 0){
printf("read timeout...\n");
exit(-2);
}
alarm(10);
printf("please intupt some char:");
fflush(stdout);
if((n == read(STDIN_FILENO, buf, MAXBUFFLEN)) < 0){
printf("read error...\n");
exit(-3);
}
alarm(0);
//buf[MAXBUFFLEN-1] = '\0';
//printf("%s\n", buf);
write(STDOUT_FILENO, buf, n);
return 0;
}
static void sig_alrm(int signo){
longjmp(env_alrm, 1);
}
非局部指的是,这不是由普通C语言goto,语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一个函数中。
#include <setjmp.h>
Int setjmp(jmp_buf env); 返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值
void longjmp(jmp_buf env,int val);在希望返回到的位置调用setjmp,此位置在main函数中,因为直接调用该函数,所以其返回值为0.setjmp参数evn的类型是一个特殊的类型jmp_buf,这一数据类型是某种形式的数组,其中存放在调用longjmp时能用来恢复栈状态的所有信息。因为需要在另一个函数中引用env变量,所以规范的处理方式是将env变量定义为全局变量。
应用:
当检查到一个错误时,则以两个参数调用longjmp函数,第一个就是在调用setjmp时所用的env,第二个参数是具有非0值的val,它将成为从setjmp处返回的值。使用第二个参数的原因是对于一个setjmp可以有多个longjmp。
注: longjmp必须在setjmp调用之后,而且longjmp必须在setjmp的作用域之内。具体来说,在一个函数中使用setjmp来初始化一个全局标号,然后只要该函数未曾返回,那么在其它任何地方都可以通过longjmp调用来跳转到 setjmp的下一条语句执行。实际上setjmp函数将发生调用处的局部环境保存在了一个jmp_buf的结构当中,只要主调函数中对应的内存未曾释放
(函数返回时局部内存就失效了),那么在调用longjmp的时候就可以根据已保存的jmp_buf参数恢复到setjmp的地方执行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h> //signal
#include <unistd.h> //alarm
#include <setjmp.h> //setjmp and longjmp
#define MAXBUFFLEN 1024
/*
*使用longjmp 及 alarm实现带超时限制调用read
*/
static void sig_alrm(int signo);//声明alarm信号处理函数
static jmp_buf env_alrm;
int main(int argc, char *argv[])
{
int n;
char buf[MAXBUFFLEN];
memset(buf, 0x00, sizeof(buf));
if(signal(SIGALRM, sig_alrm) == SIG_ERR){
printf("signal(SIGALRM) Error\n");
exit(-1);
}
//第一次调用setjmp会返回0,当longjmp被调用后,代码会跳转到setjmp处执行,setjmp将会返回longjmp设置的值。
if(setjmp(env_alrm) != 0){
printf("read timeout...\n");
exit(-2);
}
alarm(10);
printf("please intupt some char:");
fflush(stdout);
if((n == read(STDIN_FILENO, buf, MAXBUFFLEN)) < 0){
printf("read error...\n");
exit(-3);
}
alarm(0);
//buf[MAXBUFFLEN-1] = '\0';
//printf("%s\n", buf);
write(STDOUT_FILENO, buf, n);
return 0;
}
static void sig_alrm(int signo){
longjmp(env_alrm, 1);
}
[huangbin@devsrv3 ~]$ make setjmp cc setjmp.c -o setjmp [huangbin@devsrv3 ~]$ ./setjmp please intupt some char:read timeout... [huangbin@devsrv3 ~]$ ./setjmp please intupt some char:hello,world! [huangbin@devsrv3 ~]$
相关文章推荐
- 具有超时限制的read调用
- 使用alarm和setjmp实现超时控制
- 具有超时限制的read调用 (转)
- 使用longjmp,带超时限制调用read
- JavaScript用setTimeout超时调用实现setInterval间歇调用
- ES transport client底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync或者await(future超时机制)来实现类似同步调用!因此,ES transport client可以同步调用也可以异步(不过底层的socket必然是异步实现)
- 7、定义一个文件输入流,调用read(byte[] b) 方法将exercise.txt文件中的所有内容打印出来(byte数组的大小限制为5,不考虑中文编码问题)。
- AjaxPro实现异步调用,解决浏览器假死及超时问题
- linux 2.6.11内核文件IO的系统调用实现分析(read,write)(转载)
- 调用feign请求超时 feign.RetryableException: Read timed out executing POST
- 线程游戏:实现方法的超时调用
- Nachos-3.4 系统调用 实现Create Open Read Write Close
- 如何利用Guava实现方法调用超时自动中断
- 定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)
- PHP设置会话(Session)超时过期时间实现登录时间限制
- read和write系统调用以及getchar的实现
- 【转】C#多线程环境下调用 HttpWebRequest 并发连接限制 HttpClient是否有默认并发数限制? 在.Net 4.0之前,一直是依靠HttpWebRequest实现Htt
- 定义一个文件输入流,调用 read(byte[] b)方法将 exercise.txt 文件中的所有内容打印出来 (byte 数组的大小限制为 5)。
- AjaxPro实现异步调用,解决浏览器假死及超时问题
- Golang RPC调用例子程序(实现超时机制)