C/C++协程学习笔记丨C/C++实现协程及原理分析视频( 三 )
static stCoRoutineEnv_t* g_arrCoEnvPerThread[204800]
stCoRoutineEnv_t *co_get_curr_thread_env()
{
return g_arrCoEnvPerThread[ GetPid() ];
}
初始化 stCoRoutineEnv_t 时主要完成以下几步:
- 为 stCoRoutineEnv_t 申请空间并且进行初始化 , 设置协程调度器 pEpoll 。
- 创建一个空的 coroutine , 初始化其上下文环境( 有关 coctx 在后文详细介绍 ) , 将其加入到该线程的协程环境中进行管理 , 并且设置其为 main coroutine 。 这个 main coroutine 用来运行该线程主逻辑 。
struct stStackMem_t
{
stCoRoutine_t* occupy_co; // 使用该栈的协程
int stack_size; // 栈大小
char* stack_bp; // 栈的指针 , 栈从高地址向低地址增长
char* stack_buffer; // 栈底
};
使用 co_create 创建完一个协程之后 , 将调用 co_resume 来将该协程激活运行:
void co_resume( stCoRoutine_t *co )
{
stCoRoutineEnv_t *env = co->env;
// 获取当前正在运行的协程的结构
stCoRoutine_t *lpCurrRoutine = env->pCallStack[ env->iCallStackSize - 1 ];
if( !co->cStart )
{
// 为将要运行的 co 布置上下文环境
coctx_make(
co->cStart = 1;
}
env->pCallStack[ env->iCallStackSize++ ] = co; // 设置co为运行的线程
co_swap( lpCurrRoutine, co );
}
函数 co_swap 的作用类似于 Unix 提供的函数 swapcontext:将当前正在运行的 coroutine 的上下文以及状态保存到结构 lpCurrRoutine 中 , 并且将 co 设置成为要运行的协程 , 从而实现协程的切换 。 co_swap 具体完成三项工作:
- 记录当前协程 curr 的运行栈的栈顶指针 , 通过 char c; curr_stack_sp= --tt-darkmode-color: #999999;">对应于 co_resume 函数 , 协程主动让出执行权则调用 co_yield 函数 。 co_yield 函数调用了 co_yield_env , 将当前协程与当前线程中记录的其他协程进行切换:
void co_yield_env( stCoRoutineEnv_t *env )
{
stCoRoutine_t *last = env->pCallStack[ env->iCallStackSize - 2 ];
stCoRoutine_t *curr = env->pCallStack[ env->iCallStackSize - 1 ];
env->iCallStackSize--;
co_swap( curr, last);
}
前面我们已经提到过 , pCallStack 栈顶所指向的即为当前正在运行的协程所对应的结构 , 因此该函数将 curr 取出来 , 并将当前正运行的协程上下文保存到该结构上 , 并切换到协程 last 上执行 。 接下来我们以 32-bit 的系统为例来分析 libco 是如何实现协程运行环境的切换的 。
协程上下文的创建和切换libco 使用结构 struct coctx_t 来表示一个协程的上下文环境:
struct coctx_t
{
#if defined(__i386__)
void *regs[ 8 ];
#else
void *regs[ 14 ];
#endif
size_t ss_size;
char *ss_sp;
};
可以看到 , 在 i386 的架构下 , 需要保存 8 个寄存器信息 , 以及栈指针和栈大小 , 究竟这 8 个寄存器如何保存 , 又是如何使用 , 需要配合后续的 coctx_swap 来理解 。 我们首先来回顾一下 Unix-like 系统的 stack frame layout , 如果不能理解这个 , 那么剩下的内容就不必看了 。
推荐阅读
- 计算机专业大一下学期,该选择学习Java还是Python
- 假期弯道超车 国美学习“神器”助孩子变身“学霸”
- 想自学Python来开发爬虫,需要按照哪几个阶段制定学习计划
- 未来想进入AI领域,该学习Python还是Java大数据开发
- Google AI建立了一个能够分析烘焙食谱的机器学习模型
- 学习大数据是否需要学习JavaEE
- 学习“时代楷模”精神 信息科技创新助跑5G智慧港口
- 非计算机专业的本科生,想利用寒假学习Python,该怎么入手
- 为什么我喜欢C语言,却非常讨厌C++?一位国外程序员的回答
- ?优学天下带着学习机冲刺上市,智能教育硬件有多烧钱?