站在巨人的肩膀上
概述
- 协程是一种用户态的轻量级线程。
- 轻量级:相对于线程而言,协程比较轻量。在一个服务器上线程的数量不能太多,也就是上百个线程的级别,否则会产生性能问题。而协程可以轻松达到达到百万级别。
- 协作式:协程是用户态的概念,对操作系统无感知。操作系统感知不到协程的存在,只能感知到线程和进程的存在。协程的调度是在用户态自己调度。一般协程的调度是协作式的调度。
- 根据控制传递机制的不同区分出了对称协程和非对称协程。
- 非对称协程知道它的调用者,其在挂起时转让控制权给它的调用者,然后调用者根据算法调用其他非对称协程进行工作。具体来讲,非对称协程是跟一个特定的调用者绑定的,协程让出 CPU 时,只能让回给原调用者。那到底是什么东西“不对称”呢?其实,非对称在于程序控制流转移到被调协程时使用的是 call/resume 操作,而当被调协程让出 CPU 时使用的却是 return/yield 操作。此外,协程间的地位也不对等,caller 与 callee 关系是确定的,不可更改的,非对称协程只能返回最初调用它的协程。
- 对称协程都是等价的,控制权直接在对称协程之间进行传递,即对称协程在挂起时主动指明另外一个对称协程来接收控制权。对称协程与非对称协程不一样,启动之后就跟启动之前的协程没有任何关系了。协程的切换操作,一般而言只有一个操作,yield,用于将程序控制流转移给另外的协程。对称协程机制一般需要一个调度器的支持,按一定调度算法去选择 yield 的目标协程。
- sylar 的协程模块是基于 ucontext.h 实现的非对称协程库。结构体 ucontext_t 保存了程序当前运行的上下文,例如寄存器信息(这些寄存器记录了函数栈帧、代码的执行位置等信息)等。
- ucontext_t 结构体与具体平台相关,但至少会有以下四个成员:
ucontext_t *uc_link // Pointer to the context that is resumed when this context returns. sigset_t uc_sigmask // The set of signals that are blocked when this context is active. stack_t uc_stack // The stack used by this context. mcontext_t uc_mcontext // A machine-specific representation of the saved context. - ucontext.h 还提供了以下四个函数:
int getcontext(ucontext_t *ucp); - 获取当前上下文 int setcontext(const ucontext_t *ucp); - 恢复 ucp 指向的上下文,但这个函数不会返回,而是会跳转到 ucp 上下文对应的函数中执行,相当于变相调用了函数。 void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...); - 修改由 getcontext 获取到的上下文指针 ucp,将其与一个函数 func 进行绑定,支持指定 func 运行时的参数。 - 在调用 makecontext 之前,必须手动给 ucp 分配一段内存空间,存储在 ucp->uc_stack 中,这段内存空间将作为 func 函数运行时的栈空间。 - 同时也可以指定 ucp->uc_link,表示函数运行结束后恢复 uc_link 指向的上下文。 - 如果不赋值 uc_link,那 func 函数结束时必须调用 setcontext 或 swapcontext 以重新指定一个有效的上下文,否则程序就跑飞了。 - makecontext 执行完后,ucp 就与函数 func 绑定了,调用 setcontext 或 swapcontext 激活 ucp 时,func 就会被运行。 int swapcontext(ucontext_t *restrict oucp, const ucontext_t *restrict ucp); - 恢复 ucp 指向的上下文,同时将当前的上下文存储到 oucp 中。 - 和 setcontext 一样,swapcontext 也不会返回,而是会跳转到 ucp 上下文对应的函数中执行,相当于调用了函数。 - swapcontext 是 sylar 非对称协程实现的关键,线程主协程和子协程用这个接口进行上

本文介绍了sylar C++高性能分布式服务器框架中基于ucontext.h实现的非对称协程库。协程作为一种轻量级线程,能有效提升并发性能。sylar的协程模块利用线程局部变量管理协程上下文,通过swapcontext进行上下文切换。协程与IO多路复用结合,解决了高并发场景下的解决方案。此外,文章强调了协程同步的注意事项,如避免在协程中使用线程级别的锁。
最低0.47元/天 解锁文章
1984

被折叠的 条评论
为什么被折叠?



