有那位高人用过setjmp,与longjmp啊??
今天想了很久都想不明白,程序是怎么样用 setjump longjup 的//
//
// task_create(...)里面有一个setjmp();而在schedule()有一对setjmp()
// longjmp()
//
// 谁能告诉我一下,,,以上setjmp(),longjmp()之间的程序流走向
//
// schedule()中的longjmp是返回到,task_create()中setjmp呢还是返
//
// 回到 sechedule()中的setjmp中的???????
//
//
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#define STACK_SIZE 1024
#define TASK_NUM 256
#define LINUX
#ifdef LINUX
#if !defined(JB_PC) && !defined(JB_SP)
#define JB_PC 5
#define JB_SP 4
#define PTR_MANGLE(var) asm ("xorl %%gs:0x18, %0" : "=r"(var) : "0" (var))
#else
#define PTR_MANGLE(var)
#endif
#define EIP buf.__jmpbuf
#define ESP buf.__jmpbuf
#else
#define EIP buf;
#define ESP buf;
#endif
typedef unsigned long ulong;
typedef long task_t;
typedef void (*task_func) (void *args);
typedef struct task_struct{
jmp_buf buf;
int used;
ulong stack;
} task_struct;
static task_struct tasks; // 定义TCB 任务控制块
static task_t current = 0;
int task_struct_init(void)
{
int i;
for(i = 0; i < TASK_NUM; i ++)
tasks.used = 0;
tasks.used = 1;// 创建第一个任务,在主函数中运行.
return 0;
}
int task_exit(void)
{
tasks.used = 0;
schedule();
}
// 获得处理ID pid
task_t gettid(void)
{
return current;
}
int task_create(task_t *pid, task_func func, void *args)
{
static int i;
// 遍历任务,找未用的
for(i = 0; i < TASK_NUM; i ++){
if(!tasks.used){
break;
}
}
// found none
if(i == TASK_NUM) return -1;
setjmp(tasks.buf);//任务的返回点与longjmp结合吗??
tasks.stack = (ulong)args;
tasks.ESP = (ulong)(tasks.stack + STACK_SIZE - 2);
PTR_MANGLE(tasks.ESP);
tasks.EIP = (ulong)func;
PTR_MANGLE(tasks.EIP);
tasks.used = 1;
if(pid != NULL){
*pid = i;
}
return 0;
}
// 选一个任务
// 运行到最后一个任务时,返回1
int schedule(void)
{
// 保存任务运行时间信息
if(setjmp(tasks.buf)){
return 1;
}
// select a active task to run
while(1){
current = (current + 1) % TASK_NUM;
if(tasks.used){
break;
}
}
// run the task
longjmp(tasks.buf, 1);
return 0;
}
void t1(const char *ptr)
{
int i;
char ch;
for(i = 0; i < 128; i ++){
ch = '0';
printf("task %d: %s.\n", gettid(), ptr);
schedule();
}
task_exit();
}
void t2(const char *ptr)
{
while(1){
printf("task %d: %s.\n", gettid(), ptr);
// 可加入新的任务;
task_create(NULL, (task_func)&t1, "one(in two)");
schedule();
}
}
void t3(const char *ptr)
{
char *buf;
while(1){
buf = (char*)malloc(256);
printf("task %d: %s.\n", gettid(), ptr);
// printf("Please input sth. :");
// scanf("%s", buf);
// printf("Your input is : %s\n", buf);
free(buf);
schedule();
}
}
int main(void)
{
task_struct_init();
task_create(NULL, (task_func)&t1, "one");
task_create(NULL, (task_func)&t2, "two");
task_create(NULL, (task_func)&t3, "three");
while(1){
printf("task %d: core.\n", gettid());
schedule();
}
return 0;
} setjmp和longjmp与操作系统的任务切换大体是一致的,setjmp主要是用在异常处理方面,可以跨函数跳转,用作任务却换是可以的, 但得处理好堆栈,不然堆栈会被覆盖的,到google搜一下它的用法吧!
粗略看了一下:
第一次schedule()中的longjmp是返回到task_create()中setjmp ,后面当任务有sechedule()时(即换出时),重新更新任务执行的断点,longjmp是返回到sechedule()中的setjmp。 回复【1楼】charlie2008
-----------------------------------------------------------------------
// 运行到最后一个任务时,返回1
int schedule(void)
{
// 保存任务运行时间信息
if(setjmp(tasks.buf)){
return 1;
}
// select a active task to run
while(1){
current = (current + 1) % TASK_NUM;
if(tasks.used){
break;
}
}
// run the task
longjmp(tasks.buf, 1);
return 0;
}
这里我不是很明白! 不是setjmp返回是0的吗? longjmp返回非0的,程序流是怎么样进去"return1 "里面的? 回复【2楼】studyplacefor
-----------------------------------------------------------------------
这里的流程是这样的:
schedule
setjmp 返回0
执行while(1) ....
执行longjmp
跳转到setjmp处, 由于从longjmp()跳转, 返回1
执行return 1 【3楼】 theophilus
多谢你,,
页:
[1]