协程:协程,又被称为用户级线程,是在应用层被调度,可以减少因为调用系统调用而阻塞的线程切换的时间
基本原理:协程实质上可以看成是子程序、函数。一个线程上面可以运行多个协程,但是同一时间只能运行一个协程,协程在线程上的切换,是由于遇到阻塞的操作,或者主动让出线程使用权。比如,有10个协程,当前线程正在运行协程1,然后协程1执行一个recv的阻塞操作,协程的调度器能够检测到这个操作,将协程1切换出去,将协程2调度进来执行。如果没有协程的调度器,此时协程1将会由于调用recv这个系统调用且数据未到达而阻塞,进行休眠,此时操作系统将会发生线程切换,调度其他线程执行,而线程切换非常耗时,高达几十微秒,即便新执行的线程是用户任务相关的,用户任务也会多了几十微秒的线程切换的消耗。而如果使用协程,协程之间的切换只需要几百纳秒,耗时很少。这就是协程发挥优势的地方。
libco:一个高效的c/c++协程库,提供了完善的协程编程接口、常用的Socket族函数Hook等,使得业务可用同步编程模型快速迭代开发。libco默认是每一个协程独享一个运行栈,在协程创建的时候,从堆内存分配一个固定大小的内存作为该协程的运行栈,libco提供了stackless的协程共享栈模式,可以设置若干个协程共享同一个运行栈。同一个共享栈下的协程间切换的时候,需要把当前的运行栈内容拷贝到协程的私有内存中。为了减少这种内存拷贝次数,共享栈的内存拷贝只发生在不同协程间的切换。当共享栈的占用者一直没有改变的时候,则不需要拷贝运行栈。
libco的特性:
无需侵入业务逻辑,把多进程、多线程服务改造成协程服务,并发能力得到百倍提升;
支持CGI框架,轻松构建web服务(New);
支持gethostbyname、mysqlclient、ssl等常用第三库(New);
可选的共享栈模式,单机轻松接入千万连接(New);
完善简洁的协程编程接口
类pthread接口设计,通过co_create、co_resume等简单清晰接口即可完成协程的创建与恢复;
__thread的协程私有变量、协程间通信的协程信号量co_signal (New);
语言级别的lambda实现,结合协程原地编写并执行后台异步任务 (New);
基于epoll/kqueue实现的小而轻的网络框架,基于时间轮盘实现的高性能定时器;由于libco是非对称的协程机制,如果从当前协程A切换到协程B,而协程B又没有切换到下一个协程,在协程B执行结束之后,会返回到协程A执行。
libco框架体系:
接口层:协程源语、协程信号量、协程私有变量
系统函数HOOK层:socket族函数、gethostbyname、setenv/setenv
事件驱动层:epoll / kqueue、时间轮盘定时器协程接口层:实现了协程的基本源语。co_create、co_resume等简单接口负责协程创建于恢复。co_cond_signal类接口可以在协程间创建一个协程信号量,可用于协程间的同步通信。
系统函数Hook层:负责主要负责系统中同步API到异步执行的转换。对于常用的同步网络接口,Hook层会把本次网络请求注册为异步事件,然后等待事件驱动层的唤醒执行。
事件驱动层:实现了一个简单高效的异步网路框架,里面包含了异步网络框架所需要的事件与超时回调。对于来源于同步系 统函数Hook层的请求,事件注册与回调实质上是协程的让出与恢复执行。
libco源码:https://github.com/tencent/libco
本文深入解析了协程的基本原理及优势,特别是在减少线程切换耗时方面的作用。介绍了libco,一个高效的C/C++协程库,其特性包括非对称的协程机制、共享栈模式、完善的编程接口等,适用于快速开发高并发服务。
1393

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



