libgo 源码剖析(1. libgo简介与调度浅谈)

闲谈

    协程是一个很早的概念了,早些年的游戏行业中已经大规模地在使用,像lua、go这些语言中的协程原语已经相对比较完善了,一般来说直接使用就好,但是在系统后台开发上,出现的时间并不长。
    我是做C方向的后台开发,目前国内一些公司也开源了一些C协程库,但目前来说,还是在逐步完善的阶段。最早接触的C++协程库是腾讯微信的 libco,可以说是相当轻量级的协程,网上关于libco的实现的文章也是相对较多,这里的话不会去过多地叙述。

    在网上查找关于 libgo 的资料,关于代码实现的文章并没有多少,因此,打算自己看代码总结,之后的文章中,可能会针libgo和libco的部分功能进行简单对比,不足之处,希望读者指出。

背景

    因为工作需要,以前系统的异步框架已经显得不再那么地具有扩展性,异步使得原本很简单的逻辑(读->处理->写),要拆分开来成多个阶段,通过回调来响应各个事件,因此有计划地使用协程来代替。

    为什么最后选择了libgo,而没有选择更加轻量级的libco ?网上有人给出过两者的性能对比,从自旋锁、协程的数量以及栈空间、线程支持等各个角度考虑,貌似libgo完胜。
 

    性能对比数据来源于网络,并不是说libco不好,也许各自应用的场景略有不同,libco几千行的代码可以实现一个相对较完备的协程,而且经得住微信后台庞大的数据流量,自有它的优势。由于对 libgo 的代码正在研究当中,因此,暂不对两者评价。

协程

    不管是什么样的协程,最核心的内容,都是在系统发生阻塞的时候上层主动让出CPU,切换就绪协程的上下文,简要总结,有如下几个方面:

  1. 上下文切换的实现
  2. 系统函数的hook;
  3. 协程调度;
  4. 时间管理;

libgo 源码

https://github.com/yyzybb537/libgo

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 环境做研究。

  1. TODO:libgo 后续会逐步完善或增加的功能;
  2. libgo:源码实现的主目录,关于协程和调度策略的实现都在该目录下;
  3. test:测试代码;
  4. tutorial:libgo 使用教程代码;
  5. vs_proj:VS 环境下如何使用libgo。

在libgo目录下

  1. task:协程的相关实现;
  2. scheduler:协程调度的实现;
  3. debug:libgo 自带的调试功能(用于协程状态的定位等);
  4. coroutine.h:对一些常用对方法进行了重定义。
  5. netio:hook的系统调用;
  6. context:上下文的切换;
  7. pool:libgo 实现的连接池

libgo调度原理概述

    我们知道,协程是用户态线程,因此libco的话是不支持线程的。但在libgo中,线程同样是支持的,这于它的调度方式有关。

    首先我们要说的一点是,在libgo中,每个协程是一个task,libgo 的调度并不是直接作用于协程,是通过间接调度实现的。

    libgo中有调度器(scheduler)执行器(processer)的概念:

    直接负责协程调度的是执行器,它会在协程阻塞的时候切出上下文,并切入一个就绪协程的上下文去继续处理,当没有可执行的协程时,执行器就会阻塞等待,当有新到来的任务时,会继续处理;

    负责管理执行器的是调度器,对调度器而言,每个执行器是一个单独的线程,调度器做的最主要的工作,就是平衡各个执行器中的协程数量,防止饥饿效应,部分执行器过忙,部分执行器却没有task可执行,另外,如果某个执行器卡住,调度器也会将执行器中的可运行协程取出,放到负载最低的执行器上。

    当然,调度器的个数的话是支持动态扩展的。
如下图:
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要分析Linux内核的进程调度码,首先需要了解Linux内核的代码结构和相关概念。进程调度是操作系统的核心功能之一,负责决定何时以及如何将CPU分配给不同的进程。 在Linux内核中,进程调度的相关码位于kernel/sched目录下。该目录包含了与进程调度相关的各个文件和子目录,其中最重要的文件是sched.h和sched.c。 sched.h定义了与进程调度相关的数据结构、宏定义和函数原型。你可以在该文件中找到与调度算法相关的定义,如进程状态、调度类别、优先级等。 sched.c是进程调度的核心代码文件,其中实现了各种调度算法。在该文件中,你可以找到与进程调度相关的函数实现,如schedule()函数,这是Linux内核的调度函数,用于选择下一个要运行的进程。 除了sched.h和sched.c,还有一些其他的文件和子目录也与进程调度相关,如fair.c、rt.c和core.c等。fair.c中实现了CFS(完全公平调度)算法,rt.c实现了实时进程调度算法,core.c包含了通用的调度函数。 要深入理解Linux内核的进程调度码,你可以通过阅读相关文件和函数的注释来获取更多信息。此外,还可以参考一些相关的内核文档和书籍,如《Linux内核代码情景分析》和《深入理解Linux内核》等。 请注意,分析内核码需要有一定的操作系统和编程经验,并且需要花费相当的时间和精力。建议在开始分析之前,先熟悉相关的概念和基本的内核知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值