协程是一种用户空间的非抢占式线程,主要用来解决等待大量的IO操作的问题。

协程vs线程
对比使用多线程来解决IO阻塞任务,使用协程的好处是不用加锁,访问共享的数据不用进行同步操作。这里需要说明的一点是,使用协程之所以不需要加锁不是因为所有的协程只在一个线程中运行,而是因为协程的非抢占式的特点。也就是说,使用协程的话,在没主动交出CPU之前都是不会被突然切换到其它协程上的。而线程是抢占式的,使用多线程你是不能确定你的线程什么时候被操作系统调度,什么时候被切换,因此需要用锁到实现一种“原子操作”的语义。
协程vs异步回调
其实更一般更常见的做法是,使用非阻塞的IO(比如是异步IO,又或者是在syscall上自己实现的一套异步IO,如asio)并且将处理操作写在回调函数中。这样的做法一般没什么问题,但当回调函数变多,一段连贯的业务代码就会被拆分到多个回调函数之中,增加维护的成本。因此使用协程可以用同步的写法写出效果相当于是异步的代码。
利用static变量实现协程
要实现一个协程,主要的问题是如何保存函数调用的上下文。之前在网上看到一篇博客coroutines in c,用一种非常简洁的方式实现了这个保存上下文的功能。实现代码如下:
#define crBegin static int _cr_state = 0; switch(_cr_state) { case 0:
#define crReturn(x) do { _cr_state = __LINE__; return x; case __LINE__:; } while (0)
#define crFinish }
int func1() {
crBegin
while (1)
{
printf("hello world\n");
crReturn(0);
}
crFinish
}
这个代码利用了函数的static变量来保存函数调用状态。注意,由于vs2013有一个调试特性,所以vs2013的__LINE__的实现不是常量因此会编译不通过,使用gcc就可以编译。这段代码简单是简单但是有问题,比如说如果两个协程调用同一个函数,就会出错。因此博客里面提及这段代码主要是给出一个思路,如果实际使用的话这样子肯定是不行的。
利用setjmp、longjmp实现协程
前面说过,实现协程最主要的是保存函数的调用的上下文,而这些上下文主要就两个部分:1.各个寄存器的值,2.函数调用栈。C语言里可以通过setjmp来保存函数调用时,各寄存器的值。保存之后,便可以通过longjmp重现回到当初setjmp的地方(可以理解成跨函数的goto)。但是,需要注意的是,setjmp仅负责保存寄存器的值,不负责维护其函数调用栈(这个看看setjmp的jmp_buf的结构就知道了),因此必须由使用者来手动的维护这个函数调用栈。使用setjmp、longjmp的一个常见的错误就是,尝试去longjmp到一个已经执行完的函数,这时候虽然寄存器的值是当时保存的值,但是调用栈已经不是原来的调用栈了。
而我的做法是,在创建一个协程的时候在堆上申请一块空间(大小为2M)作为协程的调用栈,然后在setjmp的时候,手动更改寄存器esp的值,使其指向这个我自己创建的调用栈。因此在以后运行的时候,这个协程就会使用我提供的那块内存作为栈。
我的这个协程库提供了三个接口:
- coro_new:创建一个协程
- coro_yield:将控制权返回给调度协程
- coro_main:运行调度协程
协程的控制流程如下:
- 通过coro_main运行调度协程,并找出下一个运行的协程,运行之。
- 运行这个协程直到其调用coro_yield将控制权返还给调度协程。
- 重复以上两个步骤,直到所有协程运行完毕。
这个协程库实现的非常简单,只有100来行的代码,当然实现它的目的是为了提供一个最简单的协程模型,而不是一个功能完整、鲁棒性强的能投入实际业务运行的协程。
因此问题还是有很多的:
- 比如当在协程里面调用栈超过2M时,这个是需要处理的,现在的代码是没有做的,理应中断程序,避免写坏堆,产生随机的不可重现的问题。
- 显然在实现时没有考虑到多线程,如果在多线程环境里面运行,需要代码做同步处理。
- 现在的这个版本的协程有一个约定,在协程里调用的函数不能阻塞在syscall,这显然也是不科学的。一个完整的协程库,应该包含一些常用的syscall的非阻塞的实现,毕竟只有一个线程不能真的阻塞在这个调用上。
总结
当然实现协程还有比较一些更好的方法,比如如果能用glibc的ucontext库就可以基于这个库来实现,而不用自己手动管理函数调用的上下文了,如云风实现的协程库。
相关推荐:
AI仿写文章:开启内容创作新纪元
ChatGPT:打破语言障碍,理解与沟通的新时代,交通轨道ai
怎样使用AI写文章:释放创作潜能,提升写作效率
SEO课:让你从小白变成搜索引擎优化高手,推广自媒体营销计划
ChatGPT崩了?用户称打开是一片空白,真相竟然如此!,zzz*明星AI换脸
SEO关键词利器:如何借助精准关键词提升网站流量与排名,ai绘画客户
SEO作用:提升网站流量与品牌曝光的秘密武器,美容网站联盟平台推广
SEO北京:数字时代,企业成功的关键,湖南网站建设湖南岚鸿
AI写作免费一键生成5000字:高效创作的革命性工具
SEO确实是企业增长的关键,这些技巧让你走在行业前沿,山东网站建设信息
SEO优化10种策略:提升网站排名的有效方法,帅气ai男头白底
AI做文章:引领智能创作的未来
怎么用AI写出令人惊叹的文章?轻松搞定写作难题!
互联网时代的“搜索截流”新玩法:如何抓住流量红利,甘孜做优化网站软件
ChatGPT暂时不可用?如何高效应对并寻找最佳替代方案!,logo ai教程视频
ChatGPT手机下载后打不开?可能是这些问题导致的,解决方法在这里!,孤城ai动画
OpenPose大白话解释:让你轻松理解姿态识别的神奇技术,ai天天晴
ChatGPT登录503错误?轻松解决,快速恢复畅享智能体验!,ai怎么加植物材质效果
seo链接有什么用,seo外链是什么意思 ,one ai写作
ChatGPT3.5需要登录使用吗?AI使用的真相!,电脑版写作ai推荐怎么关闭
SEO优化与SEM广告:提升品牌曝光与流量的双重利器,ai接回头
SEO组织:让您的网站流量倍增的秘密武器,seo 绩效标准
seo重点工作是什么,seo重点工作是什么意思 ,棋谱检查ai
在线AI文章生成器开启智能创作新时代
AI文章概括缩写:让内容高效获取的智能工具,ai 处理文件
ChatGPT异常了:人工智能的极限与突破,ai and ethics
ChatGPT怎么突然不能打开了?你需要了解的原因与解决办法,ai写作有什么问题吗怎么解决
从语言助手到智能生活伙伴,未来的智能助手如何改变我们的生活,网站建设分站公司
SEO观察:2025年搜索引擎优化的新趋势与机遇,seo2是什么状态
自动AI写文章:轻松创作时代的全新利器
ChatGPT198元永久会员,开启智慧之门,体验AI的极致服务!,老孙教ai
SEO优化快:如何在短时间内实现网站流量爆发,Lacey0508ai
SEO表格:优化网站排名的秘密武器,大数据推广营销费用多少
SEO技巧提升网站流量:打造高效网站的关键策略,Ai测脸相
文章AI思维导图自动生成助力创作的智慧之源
SEO站外优化策略:提升网站排名的关键因素,遵义公司网站推广
ChatGPT怎么打不开了?解决办法,轻松恢复畅通无阻!,ai订酒店ai对话
“爱站”:开启网站优化与流量增长的新纪元,seo入门ppt
在线AI文章:为您打造全新内容创作体验
今时CMS:引领数字化转型的智慧之选,河南seo优化网站联系方式
SEO希望:如何通过SEO优化实现网站突破,迈向成功之路,品牌网站推广软件
SEO架构:提升网站流量的核心策略,东营南江全平台营销推广
seo需要什么人员,seo需要什么技能 ,画大学ai
seo用什么手法,seo方式 ,ai绘画飞翔
SEO赚钱:如何通过SEO技能在网络上实现财富自由,网站怎么建设推广平台
SEO快速排名实例:如何通过实战技巧提升网站排名,快速突破流量瓶颈,安徽ai跑步机企业
AI搜索相似文章怎么做?揭秘高效文章检索的核心技术!,程式ai软件
SEO优化:提升网站流量的终极指南,揭阳网站快速推广
SEO代做:让你的企业轻松登顶搜索引擎,快速提升曝光率,seo 提高注册量
AI助手Stut:智能时代的创新引擎,开启未来工作新篇章,ai对ai的格斗游戏