非局部跳转语句---setjmp和longjmp函数。</span>
非局部指的是,这不是由普通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
例子:
<pre name="code" class="cpp">#include <stdio.h>
#include <unistd.h>
#include <setjmp.h>
#include <stdlib.h>
typedef struct {
void *private_data;
void (*start)(void*);
jmp_buf context; //上下文切换
}Context;
static void task0(void* arg) {
printf("task0\n");
}
static void task1(void* arg) {
printf("task1\n");
}
static void task2(void* arg) {
printf("task2\n");
}
static Context *Task;
static int run_index=0;
static int index=0;
static int count = 0;
static void run(Context* c) {
c->start(c->private_data);
count++;
run_index = count % index;
printf("run_index=%d, count=%d\n", run_index, count);
sleep(1);
longjmp(Task[run_index].context,1);
}
void TaskInit(int size) {
Task = (Context*)malloc(size * sizeof(Context));
}
void createTask(void (*start)(void*), void* arg) {
Task[index].start = start;
Task[index].private_data = arg;
if(setjmp(Task[index].context)) {
printf("%s\n", "run" );
run(&Task[run_index]);
//longjmp(Task[0].context, 1);
}
index++;
}
void start() {
longjmp(Task[0].context, 1);// 开始第一个任务
}
int main() {
TaskInit(2);
createTask(task0, (void*)0);
createTask(task1, (void*)1);
createTask(task2, (void*)2);
start();
}
上面有个问题:明明只创建了2个任务,结果加了好几个都没报内存错误。我就奇怪了。不知道原因,有知道的请指教
上面只是简单的例子,可以用队列对不同的任务进行管理。有不足请包涵。