扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
如何进行libgo的源码剖析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
目前创新互联已为1000+的企业提供了网站建设、域名、虚拟空间、网站托管、企业网站设计、东台网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。闲谈协程是一个很早的概念了,早些年的游戏行业中已经大规模地在使用,像lua、go这些语言中的协程原语已经相对比较完善了,一般来说直接使用就好,但是在系统后台开发上,出现的时间并不长。
我是做C++方向的后台开发,目前国内一些公司也开源了一些C++协程库,但目前来说,还是在逐步完善的阶段。最早接触的C++协程库是腾讯微信的 libco,可以说是相当轻量级的协程,网上关于libco的实现的文章也是相对较多,这里的话不会去过多地叙述。
在网上查找关于 libgo 的资料,关于代码实现的文章并没有多少,因此,打算自己看代码总结,之后的文章中,可能会针libgo和libco的部分功能进行简单对比,不足之处,希望读者指出。
背景因为工作需要,以前系统的异步框架已经显得不再那么地具有扩展性,异步使得原本很简单的逻辑(读->处理->写),要拆分开来成多个阶段,通过回调来响应各个事件,因此有计划地使用协程来代替。
为什么最后选择了libgo,而没有选择更加轻量级的libco ?网上有人给出过两者的性能对比,从自旋锁、协程的数量以及栈空间、线程支持等各个角度考虑,貌似libgo完胜。
协程图片来源于网络
性能对比数据来源于网络,并不是说libco不好,也许各自应用的场景略有不同,libco几千行的代码可以实现一个相对较完备的协程,而且经得住微信后台庞大的数据流量,自有它的优势。由于对 libgo 的代码正在研究当中,因此,暂不对两者评价。
不管是什么样的协程,最核心的内容,都是在系统发生阻塞的时候上层主动让出CPU,切换就绪协程的上下文,简要总结,有如下几个方面:
上下文切换的实现
系统函数的hook;
协程调度;
时间管理;
libgo 目录结构说明https://github.com/yyzybb537/libgo
muhui@ASIAYANG-MB0:~/code/libgo/libgo-master$ ll total 64 -rw-r--r--@ 1 muhui staff 5913 11 7 11:20 CMakeLists.txt -rw-r--r--@ 1 muhui staff 1084 11 7 11:20 LICENSE -rw-r--r--@ 1 muhui staff 8758 11 7 11:20 README.md -rw-r--r--@ 1 muhui staff 4230 11 7 11:20 TODO drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 imgs drwxr-xr-x@ 15 muhui staff 480 11 7 11:20 libgo drwxr-xr-x@ 8 muhui staff 256 11 7 11:20 test drwxr-xr-x@ 6 muhui staff 192 11 7 11:20 third_party drwxr-xr-x@ 20 muhui staff 640 11 7 11:20 tutorial drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 vs_proj muhui@ASIAYANG-MB0:~/code/libgo/libgo-master$ cd libgo/ muhui@ASIAYANG-MB0:~/code/libgo/libgo-master/libgo$ ll total 16 drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 cls drwxr-xr-x@ 19 muhui staff 608 11 7 11:20 common drwxr-xr-x@ 6 muhui staff 192 11 7 11:20 context -rw-r--r--@ 1 muhui staff 1848 11 7 11:20 coroutine.h drwxr-xr-x@ 5 muhui staff 160 11 7 11:20 debug drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 defer -rw-r--r--@ 1 muhui staff 36 11 7 11:20 libgo.h drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 netio drwxr-xr-x@ 5 muhui staff 160 11 7 11:20 pool drwxr-xr-x@ 8 muhui staff 256 11 7 11:20 scheduler drwxr-xr-x@ 7 muhui staff 224 11 7 11:20 sync drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 task drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 timer
libgo 做的较好的一点是增加了对windows 环境的支持等,我们只针对 Linux 环境做研究。
TODO:libgo 后续会逐步完善或增加的功能;
libgo:源码实现的主目录,关于协程和调度策略的实现都在该目录下;
test:测试代码;
tutorial:libgo 使用教程代码;
vs_proj:VS 环境下如何使用libgo。
在libgo目录下
task:协程的相关实现;
scheduler:协程调度的实现;
debug:libgo 自带的调试功能(用于协程状态的定位等);
coroutine.h:对一些常用对方法进行了重定义。
netio:hook的系统调用;
context:上下文的切换;
pool:libgo 实现的连接池
我们知道,协程是用户态线程,因此libco的话是不支持线程的。但在libgo中,线程同样是支持的,这于它的调度方式有关。
首先我们要说的一点是,在libgo中,每个协程是一个task,libgo 的调度并不是直接作用于协程,是通过间接调度实现的。
libgo中有调度器(scheduler)和执行器(processer)的概念:
直接负责协程调度的是执行器,它会在协程阻塞的时候切出上下文,并切入一个就绪协程的上下文去继续处理,当没有可执行的协程时,执行器就会阻塞等待,当有新到来的任务时,会继续处理;
负责管理执行器的是调度器,对调度器而言,每个执行器是一个单独的线程,调度器做的最主要的工作,就是平衡各个执行器中的协程数量,防止饥饿效应,部分执行器过忙,部分执行器却没有task可执行,另外,如果某个执行器卡住,调度器也会将执行器中的可运行协程取出,放到负载最低的执行器上。
当然,调度器的个数的话是支持动态扩展的。
如下图:
看完上述内容,你们掌握如何进行libgo的源码剖析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联网站制作公司行业资讯频道,感谢各位的阅读!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流