赞
踩
所以在这通过例子代码尽量把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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。