首页 > 代码库 > 协程基础_context系列函数
协程基础_context系列函数
最近想看看协程,对这个的具体实现不太了解,查了下,协程最常规的做法就是基于makecontext,getcontext,swapcontext这类函数在用户空间切换用户上下文。
弄了个动态分配内存的试了试。
所以在这通过例子代码尽量把context相关的函数弄清楚先。
#include <ucontext.h> #include <stdio.h> #include <stdlib.h> static ucontext_t uctx_main, uctx_func1, uctx_func2; #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) static void func1(void) { printf("func1: started\n"); //4 printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n"); //5 if (swapcontext(&uctx_func1, &uctx_func2) == -1) //切换回func2执行 handle_error("swapcontext"); printf("func1: returning\n"); //7 } static void func2(void) { printf("func2: started\n"); //2 printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n"); //3 if (swapcontext(&uctx_func2, &uctx_func1) == -1) //切换到func1执行 handle_error("swapcontext"); printf("func2: returning\n"); //6 } int main(int argc, char *argv[]) { //注意在实际中要注意stack大小,否则可能会出现溢出. char func1_stack[16384]; char func2_stack[16384]; //获取当前进程/线程上下文信息,存储到uctx_func1中 if (getcontext(&uctx_func1) == -1) handle_error("getcontext"); //uc_stack: 分配保存协程数据的堆栈空间 uctx_func1.uc_stack.ss_sp = func1_stack; //栈头指针 uctx_func1.uc_stack.ss_size = sizeof(func1_stack); //栈大小 uctx_func1.uc_link = &uctx_main; //协程后续的context makecontext(&uctx_func1, func1, 0); //依修改得到一个新的centext if (getcontext(&uctx_func2) == -1) handle_error("getcontext"); uctx_func2.uc_stack.ss_sp = func2_stack; uctx_func2.uc_stack.ss_size = sizeof(func2_stack); /* Successor context is f1(), unless argc > 1 */ //如果argc有传参数进来,则uc_link置为空.后续代码将不再执行 uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1; makecontext(&uctx_func2, func2, 0); printf("main: swapcontext(&uctx_main, &uctx_func2)\n"); //1 //swapcontext(ucontext_t *oucp, ucontext_t *ucp) // 进行上下文切换,将当前上下文保存到oucp中,切换到ucp //将当前上下文保存到uctx_main, 并切换到uctx_func2 if (swapcontext(&uctx_main, &uctx_func2) == -1) handle_error("swapcontext"); printf("main: exiting\n"); //8 : 如argc不为空则这不会执行. exit(EXIT_SUCCESS); }
例子运行结果:
suora:/test # ./co1 5 main: swapcontext(&uctx_main, &uctx_func2) func2: started func2: swapcontext(&uctx_func2, &uctx_func1) func1: started func1: swapcontext(&uctx_func1, &uctx_func2) func2: returning suora:/test # ./co1 main: swapcontext(&uctx_main, &uctx_func2) func2: started func2: swapcontext(&uctx_func2, &uctx_func1) func1: started func1: swapcontext(&uctx_func1, &uctx_func2) func2: returning func1: returning main: exiting从运行结果看,大致弄清这几个函数了,不过我对stack大小还是没弄清楚应当怎么估算,但我把这个例子再实现了下。
弄了个动态分配内存的试了试。
/************************************************* Author: xiongchuanliang Description: coroutine suora:/test # gcc -o co2 co2.c suora:/test # ./co2 main: swapcontext(&uctx_main, &uctx_func2) func2: started func2: swapcontext(&uctx_func2, &uctx_func1) func1: started func1: swapcontext(&uctx_func1, &uctx_func2) func2: returning func1: returning main: exiting suora:/test # ./co2 3 5 main: swapcontext(&uctx_main, &uctx_func2) func2: started func2: swapcontext(&uctx_func2, &uctx_func1) func1: started func1: swapcontext(&uctx_func1, &uctx_func2) func2: returning suora:/test # **************************************************/ #include <ucontext.h> #include <stdio.h> #include <stdlib.h> ucontext_t uctx_main, uctx_func1, uctx_func2; #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) #define CONTEXT_STACK (1024*64) // 64kB typedef void (*context_func)(void); void func1(void); void func2(void); int ctx_create(ucontext_t *ctx, context_func func, ucontext_t *ctx_link, void *ss_sp, size_t ss_size); int main(int argc, char *argv[]) { if(ctx_create(&uctx_func1,func1,&uctx_main, malloc(CONTEXT_STACK),CONTEXT_STACK) == 1) return EXIT_FAILURE; if(ctx_create(&uctx_func2,func2, (argc > 1) ? NULL : &uctx_func1 , //&uctx_func1 malloc(CONTEXT_STACK),CONTEXT_STACK) == 1) { free( uctx_func1.uc_stack.ss_sp ); return EXIT_FAILURE; } printf("main: swapcontext(&uctx_main, &uctx_func2)\n"); if (swapcontext(&uctx_main, &uctx_func2) == -1) handle_error("swapcontext"); free( uctx_func1.uc_stack.ss_sp ); free( uctx_func2.uc_stack.ss_sp ); printf("main: exiting\n"); exit(EXIT_SUCCESS); } int ctx_create(ucontext_t *ctx, context_func func, ucontext_t *ctx_link, void *ss_sp, size_t ss_size) { if(getcontext(ctx) == -1) { handle_error("getcontext"); return 1; } ctx->uc_link = ctx_link; ctx->uc_stack.ss_sp = ss_sp; ctx->uc_stack.ss_size = ss_size; ctx->uc_stack.ss_flags = 0; makecontext(ctx, func, 0); return 0; } void func1(void) { printf("func1: started\n"); printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n"); if (swapcontext(&uctx_func1, &uctx_func2) == -1) handle_error("swapcontext"); printf("func1: returning\n"); } void func2(void) { printf("func2: started\n"); printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n"); if (swapcontext(&uctx_func2, &uctx_func1) == -1) handle_error("swapcontext"); printf("func2: returning\n"); }
今天先弄到这.
MAIL: xcl_168@aliyun.com
BLOG: blog.csdn.net/xcl168
协程基础_context系列函数
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。