使用C语言实现协程

本文介绍了如何使用C语言实现协程,从概念到实践,包括上下文维护、栈的管理,以及通过POSIX API进行上下文切换。通过示例代码详细解析了协程的创建、主动退出和恢复,展示了在生产者消费者模型中的应用。
摘要由CSDN通过智能技术生成

前言

协程是一个比较新的概念,它的使用场景越来越广泛,一些服务器的后台,高并发的场景,有时候就会就会用到协程,协程简单理解就是对进程,线程的一些改进和优化,其实对于线程也存在一定的开销,其包括创建,销毁,上下文切换,同步,条件变量,读写锁都涉及到用户态到内核态之间的切换,协程的改进点在于它调度开销小,不存在同步,死锁,资源竞争等问题,这是因为协程的调度是由我们用户态自定义完成的,是主动调度,而进程和线程的调度由内核完成,是被动调度,对于C语言来说有不少的协程库,比如libtask,libco,libgo,实现协程的关键在于上下文的维护,栈的维护,协程在函数运行过程中,它会主动让出CPU,保存当前的函数上下文,适当的时候,再将保存的上下文恢复到CPU继续运行,其中上下文包括寄存器,PC,堆栈.对于ARM寄存器主要包括R0-R15,R0-R12是通用寄存器,R13是堆栈指针SP,R14是链接寄存器,使用BL跳转时,自动将下一条指令的地址保存到LR中,R15是PC指针,还有一个就是ATPCS,ATPCS规定子程序通过寄存器R0-R3进行传参,多余的参数就通过堆栈进行保存,返回值保存在R0,对于协程来说,上下文切换的时候不仅仅是保存寄存器,还有信号量集等协程拥有的资源,还要将协程当前的栈内容保存下来(一个函数在执行完退出后它的栈不保存的话就会被系统自动销毁),可以参考POSIX API:getcontext(用于保存当前上下文)和setcontext(用于切换上下文),swapcontext函数(会保存当前上下文并切换到另一个上下文),makecontext(创建一个上下文)的实现,这些函数是跨平台的,不同平台下有不同的实现

初步分析

test.c

#include <stdio.h>
#include <unistd.h>
typedef struct mcontext
{
   
   int regs[16];
}mcontext_t;
int getmcontext(mcontext_t *);
int setmcontext(mcontext_t *);
int main(void)
{
   
   int count = 0;
   mcontext_t ctx;
   getmcontext(&ctx);
   printf("count : %d\n",count++);
   sleep(1);
   setmcontext(&ctx);
   puts("main exit\n");
   return 0;
}

lib.S

.globl getmcontext
getmcontext:
    /* 保存所有当前寄存器,包括sp和lr */
    str r1, [r0, #4]        // mcontext.mc_r1 = r1
    str r2, [r0, #8]        // mcontext.mc_r2 = r2
    str r3, [r0, #12]       // mcontext.mc_r3 = r3
    str r4, [r0, #16]       // mcontext.mc_r4 = r4
    str r5, [r0, #20]       // mcontext.mc_r5 = r5
    str r6, [r0, #24]       // mcontext.mc_r6 = r6
    str r7, [r0, #28]       // mcontext.mc_r7 = r7
    str r8, [r0, #32]       // mcontext.mc_r8 = r8
    str r9, [r0, #36]       // mcontext.mc_r9 = r9
    str r10, [r0, #40]      // mcontext.mc_r10 = r10
    str r11, [r0, #44]      // mcontext.mc_fp = r11
    str r12, [r0, #48]      // mcontext.mc_ip = r12
    str r13, [r0, #52]      // mcontext.mc_sp = r13
    str r14, [r0, #56]      // mcontext.mc_lr = r14
    mov r0, #0              // return 0
    mov pc, lr
.globl setmcontext
setmcontext:
    // 恢复指定context的所有寄存器,包括sp和lr
    ldr r1, [r0, #4]        // r1 = mcontext.mc_r1
    ldr r2, [r0, #8]        // r2 = mcontext.mc_r2
    ldr r3, [r0, #12]       // r3 = mcontext.mc_r3
    ldr r4, [r0, #16]       // r4 = mcontext.mc_r4
    ldr r5, [r0, #20]       // r5 = mcontext.mc_r5
    ldr r6, [r0, #24]       // r6 = mcontext.mc_r6
    ldr r7, [r0, #28]       // r7 = mcontext.mc_r7
    ldr r8, [r0, #
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值