C/C++协程学习笔记丨C/C++实现协程及原理分析视频( 四 )
文章插图
结合上图 , 我们需要知道关键的几点:
- 函数调用栈是调用者和被调用者共同负责布置的 。 Caller 将其参数从右向左反向压栈 , 再将调用后的返回地址压栈 , 然后将执行流程交给 Callee 。
- 典型的编译器会将 Callee 函数汇编成为以 push %ebp; move %ebp, %esp; sub $esp N; 这种形式开头的汇编代码 。 这几句代码主要目的是为了方便 Callee 利用 ebp 来访问调用者提供的参数以及自身的局部变量(如下图) 。
- 当调用过程完成清除了局部变量以后 , 会执行 pop %ebp; ret , 这样指令会跳转到 RA 也就是返回地址上面执行 。 这一点也是实现协程切换的关键:我们只需要将指定协程的函数指针地址保存到 RA 中 , 当调用完 coctx_swap 之后 , 会自动跳转到该协程的函数起始地址开始运行 。
int coctx_make( coctx_t *ctx, coctx_pfn_t pfn, const void *s, const void *s1 )
{
char *sp = ctx->ss_sp + ctx->ss_size - sizeof(coctx_param_t);
sp = (char*)((unsigned long)sp
coctx_param_t* param = (coctx_param_t*)sp ;
param->s1 = s;
param->s2 = s1;
memset(ctx->regs, 0, sizeof(ctx->regs));
ctx->regs[ kESP ] = (char*)(sp) - sizeof(void*);
ctx->regs[ kEIP ] = (char*)pfn;
return 0;
}
这段代码应该比较好理解 , 首先为函数 coctx_pfn_t 预留 2 个参数的栈空间并对其到 16 字节 , 之后将实参设置到预留的栈上空间中 。 最后在 ctx 结构中填入相应的 , 其中记录 reg[kEIP] 返回地址为函数指针 pfn , 记录 reg[kESP] 为获得的栈顶指针 sp 减去一个指针长度 , 这个减去的空间是为返回地址 RA 预留的 。 当调用 coctx_swap 时 , reg[kEIP] 会被放到返回地址 RA 的位置 , 待 coctx_swap 执行结束 , 自然会跳转到函数 pfn 处执行 。
coctx_swap(ctx1, ctx2) 在 coctx_swap.S 中实现 。 这里可以看到 , 该函数并没有使用 push %ebp; move %ebp, %esp; sub $esp N; 开头 , 因此栈空间分布中不会出现 ebp 的位置 。 coctx_swap 函数主要分为两段 , 其首先将当前的上下文环境保存到 ctx1 结构中:
leal 4(%esp), %eax // eax = old_esp + 4
movl 4(%esp), %esp // 将 esp 的值设为--tt-darkmode-color: #999999;">这里需要注意指令 leal 和 movl 的区别 。 leal 将 eax 的值设置成为 esp 的值加 4 , 而 movl 将 esp 的值设为 esp+4 所指向的内存上的值 , 也就是参数 ctx1 的地址 。 之后该函数将 ctx2 中记录的上下文恢复到 CPU 寄存器中 , 并跳转到其函数地址处运行:
movl 4(%eax), %esp // 将 esp 的值设为--tt-darkmode-color: #999999;">上面的代码看起来可能有些绕:
- 首先 line 1 将 esp 设置为参数 ctx2 的地址 , 后续的 popl 操作均在 ctx2 的内存空间上执行 。
- line 2-9 将 ctx2->regs[] 中的内容恢复到相应的寄存器中 。 还记得在前面 coctx_make 中设置了 regs[EIP] 和 regs[ESP] 吗?这里刚好就对应恢复了相应的值 。
- 当执行完 line 9 之后 , esp 已经指向了 ctx2 中新的栈顶指针 , 由于在 coctx_make 中预留了一个指针长度的 RA 空间 , line 10 刚好将新的函数指针--tt-darkmode-color: #979797;">如何使用 libco我们首先以 libco 提供的例子 example_echosvr.cpp 来介绍应用程序如何使用 libco 来编写服务端程序 。在 example_echosvr.cpp 的 main 函数中 , 主要执行如下几步:
推荐阅读
- 计算机专业大一下学期,该选择学习Java还是Python
- 假期弯道超车 国美学习“神器”助孩子变身“学霸”
- 想自学Python来开发爬虫,需要按照哪几个阶段制定学习计划
- 未来想进入AI领域,该学习Python还是Java大数据开发
- Google AI建立了一个能够分析烘焙食谱的机器学习模型
- 学习大数据是否需要学习JavaEE
- 学习“时代楷模”精神 信息科技创新助跑5G智慧港口
- 非计算机专业的本科生,想利用寒假学习Python,该怎么入手
- 为什么我喜欢C语言,却非常讨厌C++?一位国外程序员的回答
- ?优学天下带着学习机冲刺上市,智能教育硬件有多烧钱?