我们已经大致知道event_base的初始化过程,上一节的最后给出了一张event_base中管理的各种数据结构的图示。本节就是要探究event_base是如何利用这些结构处理事件的。
抽丝剥茧libevent——初始化event_base
event_base是libevent里另外一个核心的结构,它是存放各种事件集的容器,同时也是libevent事件循环(event loop)的主要结构。和event一样,它也是不透明结构。
每个libevent程序都必须创建至少一个event_base结构。如果需要多个线程监听I/O的话,需要为每个线程分配一个event_base(推荐的做法是one loop per thread)。
本文可能不会详尽event_base每个字段含义,libevent盘根错节,先抽取出一条主线,逐渐深入每一处细节。
抽丝剥茧libevent——初识event
从这章起正式进入libevent的源码部分,libevent是事件驱动(event-driven)的网络库,事件是一切操作的基本单元,那么就从event说起。
首先event是一个不透明结构(opaque structure),对于使用者来说,无需关心它的内部数据结构。所有对event的操作,都需要通过libevent提供的接口,不能自己私自操作其中的数据(不得不感慨一下,指针还是给了程序员太大的自由了)。这样做的好处主要有两个,通用编程技法一章已经提到过了:信息封装和二进制兼容。对于一个动态库来讲,这两个特性尤为重要。
抽丝剥茧libevent——reactor模式
现代网络库通常基于reactor模式或者proactor模式。使用这两种模式,可以将具体业务从网络框架中分离出去,从而降低耦合。 这两者的基本概念是:如何深刻理解reactor和proactor?。
由于Linux缺少完备的系统异步I/O支持,proactor模式在LInux上玩不转。Windows上的IOCP通常可以用来实现proactor。
libevent采用的是reactor模式。
抽丝剥茧libevent——通用的编程技法
阅读libevent源码时,搞懂它的网络处理逻辑,应该是一件比较容易的事儿。但是我们不应该局限于此,深入每一处细节,体会作者的设计意图才是学习libevent的最佳”食用”方式。学习掌握这些开源库里边的通用编程技法,对提高我们的编程能力大有好处。
抽丝剥茧libevent——前言
网上已经流传了各种版本的libevent源码剖析了,今天再开这个系列的剖析,似乎有点凑热闹的意思了。为了对得起标题里的”抽丝剥茧”,我打算深入libevent的每一处细节,从最根本处分析libevent是如何工作的。
由于libevent是跨平台的网络库,后端的IO复用模型会因所在平台的不同而有所差异,但是原理大致相当,我选择的是最常用的linux平台。
目前心里边有一个大纲:先从libevent通用的一些编程技法讲起,如果是第一次阅读开源项目,难免会对一些常见的C语言编程技巧感到陌生(例如C语言里实现多态)。然后升入介绍epoll的用法 ,再通过实现一个Echo服务器介绍Reactor设计模式,到这里差不多能够明白libevent工作流是怎么回事了,这之后再从libevent的数据结构(struct event,struct event_base)剖析过来,一点点深入细节,抽丝剥茧。最后是libevent的高级功能以及应用。