Libco源码分析(一)

自从拿了腾讯实习offer后就没有再学习了,今天打算重新开始学习,打算将我寒假学习协程方面的知识记录下来,也为后面秋招做准备。

Libco源码地址:Libco

接下来分六个章节从源码角度介绍Libco。

  1. 底层协程切换的原理
  2. 时间轮的设计
  3. 协程原语的设计
  4. 协程的调度
  5. 协程的同步
  6. 一些零碎的功能

然后再根据我对Libco的理解再进行一些拓展。

  1. 网络库的封装
  2. 实现类似Golang中Channel用于协程间通讯
  3. 实现一个类似Golang中select用于配合Channel
  4. 实现无栈协程

感谢Libco,如果没有根据Libco写的协程库,作为一个三本的学生或许不太可能获得腾讯的面试机会并最终拿到实习offer的。

协程的概念

协程的提出是对标线程的,首先要了解为什么会有协程,他是用来解决什么的。这里主要聊一些很多人对于协程的误区。

了解过协程的都知道协程是比线程更轻量级的存在,线程的切换是在内核态,而协程的切换是在用户态。既然协程切换更快,那是不是不用线程都用协程好呢,那为什么Java语言没有对协程的支持?

实际上协程解决的问题并不是程序执行的效率问题,而是用来将异步的代码转换为同步逻辑的代码。如果用过Asio,你肯定会被那异步的逻辑恶心到,读取或发送一个数据不是流式的按顺序执行,而是注册一个回调函数在读事件或写事件触发后回调,如果逻辑复杂以后,在注册的回调函数中通常还会嵌套许多的异步回调函数,回调里面有回调,回调里面又有回调,这简直不符合人类的思维逻辑啊!如果我们能够像我们刚开始学网络编程时,read数据处理完以后直接write,这种顺序的逻辑该有多好啊!

那为什么要使用异步的写法呢?因为在一个线程下,如果要处理多个连接,必然会用到IO复用,而不能像处理一个连接一样按照顺序来写逻辑。Reactor模式下我们只能通过注册各种事件回调来完成。如果我们不使用协程,我想处理多个连接又想用处理单个连接一样写逻辑该怎么办?有一种网络模型叫做半同步/半反应堆,他就是将每一个连接分配给其中一个线程,而每个线程只处理一个连接,这样每个线程就是同步的逻辑了。但是线程是很昂贵的,一个线程处理一个连接在高并发情况下是非常不合理的。。。

所以协程就应运而生了。如果在一个线程中,每个连接都是一个独立的逻辑,他们拥有独立的栈,独立的代码,独立的寄存器。IO复用对于他们来说是透明的,每个连接只需要处理自己的事件,遇到需要等待的函数时自动切换到其他协程,而事件的到来时就像线程一样唤醒他们,这样我们就不需要考虑什么可读可写啦!太爽了!

上面说的一个独立的逻辑,他们拥有独立的栈,独立的代码,独立的寄存器是不是很熟悉,这不就是线程嘛!所以协程的本质就是在用户态模拟线程的一系列操作。但是协程和线程的适用场景完全不同,而且还是有很多差别的,具体的差别相信读完Libco源码后你一定就知道了!

接下来我将会自底向上,首先分析协程切换的本质,这部分需要一些汇编的知识,但也不难,至少我看Libco时对汇编语言0基础慢慢学过来的。另外理解函数调用的过程会更加好理解协程的切换,推荐《程序员的自我修养》10.2栈与调用惯例。

你可能感兴趣的:(Libco)