[linux奇技淫巧] 用户态线程coroutine

Coroutine即教科书上提到的“协程”,可以认为是用户态的线程,在它看来thread就是CPU。

在一个thread内可以启动任意多个协程,它们放佛是在同一个“CPU”上运行的多个线程,而与线程的最大不同是,它并非”抢占式“的,因此它让出“CPU”的唯一方式是自己主动放弃执行,保存现场后跳转到其他协程执行。

协程的切换开销远远小于内核对于线程的切换开销,因此对于IO密集型的程序,使用协程的优势在于用户可以像写同步IO一样,无需关心IO异步接口的细节。封装等待IO返回的逻辑,跳转到coroutine库进行调度。减小使用多个线程做同步IO带来的内核大量线程切换的开销。

linux下的swapcontext系列函数提供了协程上下文创建和切换的封装,使用这一组函数可以自己实现简单的coroutine库,使用一个协程作为调度器,其他协程让出“CPU”时都先跳转到调度器,由调度器决定跳转到哪个等待调度的协程继续工作,以此实现包括启动、切换、退出协程的逻辑。

swapcontext的问题是内部调用了内核的锁,造成性能不佳,这里可以使用_longjmp替代swapcontext来优化性能,但是由于_longjmp并未提供创建协程上下文的封装,自己手动构建的过程极其反人类,一个取巧的办法是使用makecontext/swapcontext来构建协程上下文并执行第一次跳转,后续的跳转则使用_longjmp。

一个简单的coroutine例子可以参考我的github。

https://github.com/kayaklee/uthread

发表评论

电子邮件地址不会被公开。 必填项已用*标注