-
Notifications
You must be signed in to change notification settings - Fork 2
Home
本wiki根据commit 7ec84872b8ac4beb81ce252bc164224d23faf2f4
所写,如需对照代码,请查看此commit下的代码。
本文档对libgo的设计进行梳理,对libgo中重要的代码进行分析,包括协程的创建,上下文切换,调度器的设计等。
介绍每一部分时首先对其设计思路进行介绍,之后根据类图UML,介绍涉及的函数,对函数流程和其中涉及的数据结构和算法进行介绍,例如Scheduler
中使用的双端队列及Dispatcher
中协程负载均衡使用的算法。
epoll 全称 eventpoll,是 linux 内核实现IO多路复用(IO multiplexing)的一个实现。IO多路复用的意思是在一个操作里同时监听多个输入输出源,在其中一个或多个输入输出源可用的时候返回,然后对其的进行读写操作。
通过一个epoll 实例,向其中添加自己感兴趣的fd,fd就绪可以从epoll中获取。
-
epoll_create1
: 创建一个epoll实例,文件描述符 -
epoll_ctl
: 将监听的文件描述符添加到epoll实例中,实例代码为将标准输入文件描述符添加到epoll中 -
epoll_wait
: 等待epoll事件从epoll实例中发生, 并返回事件以及对应文件描述符
epoll
事件有两种模型,边沿触发:edge-triggered (ET), 水平触发:level-triggered (LT)
水平触发(level-triggered)
- socket接收缓冲区不为空 有数据可读 读事件一直触发
- socket发送缓冲区不满 可以继续写入数据 写事件一直触发
边沿触发(edge-triggered)
- socket的接收缓冲区状态变化时触发读事件,即空的接收缓冲区刚接收到数据时触发读事件
- socket的发送缓冲区状态变化时触发写事件,即满的缓冲区刚空出空间时触发读事件
边沿触发仅触发一次,水平触发会一直触发。
libgo的目录结构如上图,libgo文件夹存放libgo的代码,test存放测试代码,tutorial存放教程代码。其中libgo.libgo的目录结构为:
- cls: 协程本地变量
- common: 队列、错误定义、config等
- context: 上下文切换
- debug: 调试、协程事件监听器
- defer: 延迟执行。Go语言的 defer 语句会将其后面跟随的语句进行延迟处理
- netio: 网络相关syscall hook
- pool: 协程池
- routine_sync: channel、条件变量、mutex
- routine_sync_libgo: 定义了协程的switcher,供Rutex在”协程同步“相关的操作使用。
- scheduler: 协程调度
- sync: channel、条件变量、mutex
- task: 协程task定义
- timer: 定时器
1-libgo使用 该文档介绍了如何使用libgo,从代码编译开始。libgo的使用主要在tutorial文件夹下,包含了多种使用示例。
2-scheduler 该文档介绍了libgo中协程调度的全部内容,首先调度器的整体结构,之后对调度系统包含的三个角色(scheduler、processer和dispatcher)分别进行介绍。还介绍了协程的重要结构Task和系统调用HOOK。
3-gc 该文档介绍了libgo中gc相关的内容,包括两个部分scheduler和task中的gc机制。
4-debug 该文档介绍libgo中调试相关内容。
5-锁机制 该文档介绍协程锁和协程读写锁
6-channel 该文档介绍libgo的channel机制
7-switcher 该文档介绍libgo为了实现锁机制实现的switcher
8-timer 该文档主要介绍libgo中的定时器机制,并主要介绍自定义定时器CoTimer