ucontext的介绍

http://blog.csdn.net/qq910894904/article/details/41911175

协程的介绍

https://en.wikipedia.org/wiki/Coroutine

风云的c库

http://blog.codingnow.com/2012/07/c_coroutine.html

https://github.com/cloudwu/coroutine/

腾讯的开源c++库

https://code.csdn.net/Tencent/libco/tree/master

微信的coroutine的应用

http://www.58maisui.com/2016/06/16/a-210/

http://blog.csdn.net/brainkick/article/details/48676403

http://opensource.tencent.com/libco.html

getcontext makecontext setcontext swapcontext介绍

http://blog.amalcao.me/blog/2014/07/10/cxie-cheng-zhi-ucontextpian-shang/

https://github.com/zfengzhen/Blog/blob/master/article/ucontext%E7%B0%87%E5%87%BD%E6%95%B0%E5%AD%A6%E4%B9%A0.md

所谓 “ucontext” 机制是 GNU C 库提供的一组用于创建、保存、切换用户态执行“上下文”(context)的API,可以看作是 “setjmp/long_jmp” 的“升级版”,主要包括以下四个函数:

void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
int swapcontext(ucontext_t *oucp, ucontext_t *ucp);
int getcontext(ucontext_t *ucp);
int setcontext(const ucontext_t *ucp);

结构体 ucontext_t 和上述4个函数声明一起定义在系统头文件<ucontext.h> 中,该类型的具体实现与体系结构相关,但规范要求其至少要包含以下字段:

typedef struct ucontext {
struct ucontext *uc_link;
sigset_t uc_sigmask;
stack_t uc_stack;
mcontext_t uc_mcontext;
...
} ucontext_t;

其中 sigset_t 和 stack_t 定义在标准头文件 <signal.h> 中, uc_link 字段保存当前context结束后继续执行的context记录, uc_sigmask 记录该context运行阶段需要屏蔽的信号,uc_stack 是该context运行的栈信息, 最后一个字段uc_mcontext 则保存具体的程序执行上下文——如PC值、堆栈指针、寄存器值等信息——其实现方式依赖于底层运行的系统架构,是平台、硬件相关的。

下面具体来看每个函数的功能:

  • int makecontext(ucontext_t *ucp, void (*func)(), int argc, ...) 该函数用以初始化一个ucontext_t类型的结构,也就是我们所说的用户执行上下文。函数指针func指明了该context的入口函数,argc指明入口参数个数,该值是可变的,但每个参数类型都是int型,这些参数紧随argc传入。 另外,在调用makecontext之前,一般还需要显式的指明其初始栈信息(栈指针SP及栈大小)和运行时的信号屏蔽掩码(signal mask)。 同时也可以指定uc_link字段,这样在func函数返回后,就会切换到uc_link指向的context继续执行。

  • int setcontext(const ucontext_t *ucp) 该函数用来将当前程序执行线索切换到参数ucp所指向的上下文状态,在执行正确的情况下,该函数直接切入到新的执行状态,不再会返回。比如我们用上面介绍的makecontext初始化了一个新的上下文,并将入口指向某函数entry(),那么setcontext成功后就会马上运行entry()函数。

  • int getcontext(ucontext_t *ucp) 该函数用来将当前执行状态上下文保存到一个ucontext_t结构中,若后续调用setcontext或swapcontext恢复该状态,则程序会沿着getcontext调用点之后继续执行,看起来好像刚从getcontext函数返回一样。 这个操作的功能和setjmp所起的作用类似,都是保存执行状态以便后续恢复执行,但需要重点指出的是:getcontext函数的返回值仅能表示本次操作是否执行正确,而不能用来区分是直接从getcontext操作返回,还是由于setcontext/swapcontex恢复状态导致的返回,这点与setjmp是不一样的。

  • int swapcontext(ucontext_t *oucp, ucontext_t *ucp) 理论上,有了上面的3个函数,就可以满足需要了(后面讲的libgo就只用了这3个函数,而实际只需setcontext/getcontext就足矣了),但由于getcontext不能区分返回状态,因此编写上下文切换的代码时就需要保存额外的信息来进行判断,显得比较麻烦。 为了简化切换操作的实现,ucontext 机制里提供了swapcontext这个函数,用来“原子”地完成旧状态的保存和切换到新状态的工作(当然,这并非真正的原子操作,在多线程情况下也会引入一些调度方面的问题,后面会详细介绍)。 为了进一步理解swapcontext这个函数的设计目的,可以尝试利用getcontext/setcontext完成同样的功能,你需要怎样编写代码? 同时,也不妨思考一下下面这段代码的执行结果(该例出自维基百科Setcontext 条目):

#include <stdio.h>
#include <ucontext.h>
#include <unistd.h> int main(int argc, char *argv[]) {
ucontext_t context; getcontext(&context);
puts("Hello world");
sleep(1);
setcontext(&context);
return 0;
}

小结

可以看出,用ucontext机制实现一个“协程”系统并不困难。 实际上,每个运行上下文(ucontext_t)就直接对应于“协程”概念,对于协程的“创建”(Create)、“启动” (Spawn)、“挂起” (Suspend)、“切换” (Swap)等操作,很容易通过上面的4个API及其组合加以实现,需要的工作仅在于设计一组数据结构保存暂不运行的context结构,提供一些调度的策略即可。 这方面的开源实现有很多,其中最著名的就是Go的前身,libtask库。

对于将“协程”映射到多OS线程执行的情形,就要稍稍复杂一些,但主要的问题是集中在共享任务队列的实现、调度线程间的互斥等,至于“协程”的映射问题,与单线程情况没有太大的区别。 对于这方面的开源借鉴,当然首推Go的运行时 —— 但由于标准Go实现没有使用GNU C库,而是自行设计了包括C编译器在内的整套工具链,因而就没有直接采用ucontext机制(尽管其内部实现机制与ucontext原理类似)。

以后有机会,会再分析一下GCC Go语言前端的运行时实现——libgo。 libgo的调度器部分基本用C开发并由GCC编译,“goroutine”(Go语言中相对于“协程”的概念)也直接以“ucontext”机制实现,其代码对于分析C语言下“协程”系统实现方法而言,具有较高的参考价值。

ucontext-人人都可以实现的简单协程库的更多相关文章

  1. 写个百万级别full-stack小型协程库——原理介绍

    其实说什么百万千万级别都是虚的,下面给出实现原理和测试结果,原理很简单,我就不上图了: 原理:为了简单明了,只支持单线程,每个协程共享一个4K的空间(你可以用堆,用匿名内存映射或者直接开个数组也都是可 ...

  2. 一个“蝇量级” C 语言协程库

    协程(coroutine)顾名思义就是“协作的例程”(co-operative routines).跟具有操作系统概念的线程不一样,协程是在用户空间利用程序语言的语法语义就能实现逻辑上类似多任务的编程 ...

  3. C高级 跨平台协程库

    1.0 协程库引言 协程对于上层语言还是比较常见的. 例如C# 中 yield retrun, lua 中 coroutine.yield 等来构建同步并发的程序. 本文就是探讨如何从底层实现开发级别 ...

  4. 基于ASIO的协程库orchid简介

    什么是orchid? orchid是一个构建于boost库基础上的C++库,类似于python下的gevent/eventlet,为用户提供基于协程的并发模型. 什么是协程: 协程,即协作式程序,其思 ...

  5. Stackful 协程库 libgo(单机100万协程)

    libgo 是一个使用 C++ 编写的协作式调度的stackful协程库, 同时也是一个强大的并行编程库. 设计之初是为高并发分布式Linux服务端程序开发提供底层框架支持,可以让链接进程序的同步的第 ...

  6. libco协程库上下文切换原理详解

    缘起 libco 协程库在单个线程中实现了多个协程的创建和切换.按照我们通常的编程思路,单个线程中的程序执行流程通常是顺序的,调用函数同样也是 “调用——返回”,每次都是从函数的入口处开始执行.而li ...

  7. CPU的最小执行单位是线程,协程不需要qt支持...直接用现成的协程库就行了

    协程也就在I/O操作上才有优势,Qt事件循环,本事很多I/O已经是异步了,利用好异步(虽然都说异步有点反人类思维).因为CPU的执行最小单位是线程,协程也只是在其之上又调度而已. 我的意思是利用好异步 ...

  8. 协程库st(state threads library)原理解析

    协程库state threads library(以下简称st)是一个基于setjmp/longjmp实现的C语言版用户线程库或协程库(user level thread). 这里有一个基本的协程例子 ...

  9. libaco: 一个极速的轻量级 C 非对称协程库 🚀 (10 ns/ctxsw + 一千万协程并发仅耗内存 2.8GB + Github Trending)

    0 Name 简介 libaco - 一个极速的.轻量级.C语言非对称协程库. 这个项目的代号是Arkenstone 

随机推荐

  1. VI ORB-SLAM初始化与VINS初始化对比(将vi orb-slam初始化方法移植到vins中)

    初始化时需要求出的变量:相机和imu外参r t.重力g.尺度s.陀螺仪和加速度计偏置ba bg. 下面对两种算法初始化的详细步骤进行对比: 求陀螺仪偏置bg 求解公式相同,求解方法不同.公式如下,VI ...

  2. 对ThreadLocal的源码解读

    早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. 功能 ...

  3. 分布式服务框架 Zookeeper — 管理分布式环境中的数据

    本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们理解. ...

  4. 监听Google Player下载并获取包名等信息

    一.解决思路 通过监听ContentObserver监听下载路径content://downloads 二.具体步骤 1 设置监听器 context.getContentResolver() .reg ...

  5. python之GIL(Global Interpreter Lock)

    一 介绍 ''' 定义: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple nati ...

  6. Andorid Studio 模块化开发相关配置

    Andorid Studio 模块化开发相关配置 下面以宿主APP模块和Uer_Module模块为例: 第一步:在项目根目录gradle.properties配置文件中添加如下代码 isNeedUse ...

  7. jQuery中turn.js(翻页效果)学习笔记

    Turn.js是一个内置的jQuery翻页插件1 html中引入<script type="text/javascript" src="js/turn.js&quo ...

  8. 006 --MySQL索引原理

    一 .索引的概念? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化 ...

  9. Web服务架构

    # Web服务架构 ### Web服务模型-- 服务提供者.服务请求者.服务注册中心,服务注册中心是一个可选的角色. 现在的Web服务不仅限于WSDL,还有RESTful. - 服务提供者.即Web服 ...

  10. RabbitMQ和Kafka,更加便捷高效的消息队列使用方式,请放心食用

    一.RabbitMQ实例介绍RabbitMQ实例由华为云分布式消息服务(DMS)团队打造,实例采用物理隔离的方式部署,租户独占RabbitMQ实例.一键式部署,完全兼容开源RabbitMQ的使用方式, ...