1.为什么要有协程?
同步的编程方式,异步的性能。同步编程时,我们需要等待io就绪。但是在协程这里,我们使用一种机制,当io需要等待时,就切到下一个io,之后当之前的io就绪时,再切换回来继续处理就绪事件。
2.协程的原语操作
yield 让出
resume 恢复
3.协程的切换
切换有三种方式
1.setjmp/longjmp
2.ucontext
3.asm code
汇编实现切换的优缺点
1.性能较高
2.容易理解
3.容易实现
a.有门槛
b.不同体系机构,汇编代码不一样
c.跨平台较弱
4.协程的struct如何定义
5.协程的scheduler如何定义
6.调度策略如何实现
7.如何与posix api兼容
8.协程多核模式
9.协程的性能如何测试?
sync() { send(request); recv(response); }
response_cb() { recv(); } async() { send(request, response_cb); }
#include <stdio.h> #include <ucontext.h> //ucontext //getcontext(&context) //makecontext(&context, func, arg); //swapcontext(¤t_context, &next_context); ucontext_t ctx[2]; ucontext_t main_ctx; int count = 0; //12314 void fun1() { while(count++ < 100) { printf("1"); swapcontext(&ctx[0], &ctx[1]); printf("3"); } } void func2() { while(count++ < 100) { printf("2"); swapcontext(&ctx[1], &ctx[0]); printf("4"); } } int main() { char stack1[2048] = {0}; char stack2[2048] = {0}; getcontext(&ctx[0]); ctx[0].uc_stack.ss_sp = stack1; ctx[0].uc_stack.ss_size = sizeof(stack1); ctx[0].uc_link = &main_ctx; makecontext(&ctx[0], fun1, 0); getcontext(&ctx[1]); ctx[1].uc_stack.ss_sp = stack1; ctx[1].uc_stack.ss_size = sizeof(stack1); ctx[1].uc_link = &main_ctx; makecontext(&ctx[1], fun2, 0); printf("swapcontext\n"); swapcontext(&main_ctx, &ctx[0]); printf("\n"); }
jmp_buf env; //setjmp, longjmp void func(int arg) { printf("func\n"); longjmp(env, ++arg); printf("longjmp complete\n"); } int main() { int ret = setjmp(env); if (ret == 0) { printf("ret == 0\n"); func(ret); } else if (ret == 1) { printf("ret == 1\n"); func(ret); } printf("ret : %d\n", ret); }