前面讲到,整个libevent本身就是一个Reactor,因此本节将专门对Reactor模式进行必要的介绍,并列出libevnet中的几个重要组件和Reactor的对应关系,在后面的章节中可能还会提到本节介绍的基本概念。
1 Reactor的事件处理机制
首先来回想一下普通函数调用的机制:程序调用某函数?函数执行,程序等待?函数将结果和控制权返回给程序?程序继续处理。
Reactor释义“反应堆”,是一种事件驱动机制。和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为“回调函数”。使用Libevent也是想Libevent框架注册相应的事件和回调函数;当这些时间发声时,Libevent会调用这些回调函数处理相应的事件(I/O读写、定时和信号)。
    用“好莱坞原则”来形容Reactor再合适不过了:不要打电话给我们,我们会打电话通知你。
    举个例子:你去应聘某xx公司,面试结束后。
“普通函数调用机制”公司HR比较懒,不会记你的联系方式,那怎么办呢,你只能面试完后自己打电话去问结果;有没有被录取啊,还是被据了;
“Reactor”公司HR就记下了你的联系方式,结果出来后会主动打电话通知你:有没有被录取啊,还是被据了;你不用自己打电话去问结果,事实上也不能,你没有HR的留联系方式。
2 Reactor模式的优点
Reactor模式是编写高性能网络服务器的必备技术之一,它具有如下的优点:
    1)响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;
    2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;
    3)可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源;
    4)可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性;
3 Reactor模式框架
    使用Reactor模型,必备的几个组件:事件源、Reactor框架、多路复用机制和事件处理程序,先来看看Reactor模型的整体框架,接下来再对每个组件做逐一说明。
 
1) 事件源
Linux上是文件描述符,Windows上就是Socket或者Handle了,这里统一称为“句柄集”;程序在指定的句柄上注册关心的事件,比如I/O事件。
2) event demultiplexer——事件多路分发机制
由操作系统提供的I/O多路复用机制,比如select和epoll。
    程序首先将其关心的句柄(事件源)及其事件注册到event demultiplexer上;
当有事件到达时,event demultiplexer会发出通知“在已经注册的句柄集中,一个或多个句柄的事件已经就绪”;
    程序收到通知后,就可以在非阻塞的情况下对事件进行处理了。
对应到libevent中,依然是select、poll、epoll等,但是libevent使用结构体eventop进行了封装,以统一的接口来支持这些I/O多路复用机制,达到了对外隐藏底层系统机制的目的。
3) Reactor——反应器
    Reactor,是事件管理的接口,内部使用event demultiplexer注册、注销事件;并运行事件循环,当有事件进入“就绪”状态时,调用注册事件的回调函数处理事件。
对应到libevent中,就是event_base结构体。
一个典型的Reactor声明方式class Reactor
{
public:
    int register_handler(Event_Handler *pHandler, int event);
    int remove_handler(Event_Handler *pHandler, int event);
    void handle_events(timeval *ptv);
    // ...
};
4) Event Handler——事件处理程序
    事件处理程序提供了一组接口,每个接口对应了一种类型的事件,供Reactor在相应的事件发生时调用,执行相应的事件处理。通常它会绑定一个有效的句柄。
对应到libevent中,就是event结构体。
下面是两种典型的Event Handler类声明方式,二者互有优缺点。class Event_Handler
{
public:
    virtual void handle_read() = 0;
    virtual void handle_write() = 0;
    virtual void handle_timeout() = 0;
    virtual void handle_close() = 0;
    virtual HANDLE get_handle() = 0;
    // ...
};
class Event_Handler
{
public:
    // events maybe read/write/timeout/close .etc
    virtual void handle_events(int events) = 0;
    virtual HANDLE get_handle() = 0;
    // ...
};
4 Reactor事件处理流程
前面说过Reactor将事件流“逆置”了,那么使用Reactor模式后,事件控制流是什么样子呢?
可以参见下面的序列图。
 
5 小结
上面讲到了Reactor的基本概念、框架和处理流程,对Reactor有个基本清晰的了解后,再来对比看libevent就会更容易理解了,接下来就正式进入到libevent的代码世界了,加油!

libevent源码深度剖析二相关推荐

  1. libevent源码深度剖析十二

    libevent源码深度剖析十二 --让libevent支持多线程 张亮 Libevent本身不是多线程安全的,在多核的时代,如何能充分利用CPU的能力呢,这一节来说说如何在多线程环境中使用libev ...

  2. libevent源码深度剖析

    原文地址:http://blog.csdn.net/sparkliang/article/details/4957667 libevent源码深度剖析一 --序幕 张亮 1 前言 Libevent是一 ...

  3. libevent源码深度剖析十一

    libevent源码深度剖析十一 --时间管理 张亮 为了支持定时器,Libevent必须和系统时间打交道,这一部分的内容也比较简单,主要涉及到时间的加减辅助函数.时间缓存.时间校正和定时器堆的时间值 ...

  4. libevent源码深度剖析八

    libevent源码深度剖析八 --集成信号处理 张亮 现在我们已经了解了libevent的基本框架:事件管理框架和事件主循环.上节提到了libevent中I/O事件和Signal以及Timer事件的 ...

  5. libevent源码深度剖析十

    libevent源码深度剖析十 --支持I/O多路复用技术 张亮 Libevent的核心是事件驱动.同步非阻塞,为了达到这一目标,必须采用系统提供的I/O多路复用技术,而这些在Windows.Linu ...

  6. libevent源码深度剖析一

    libevent源码深度剖析一 --序幕 张亮 1 前言 Libevent是一个轻量级的开源高性能网络库,使用者众多,研究者更甚,相关文章也不少.写这一系列文章的用意在于,一则分享心得:二则对libe ...

  7. libevent 源码深度剖析十三

    libevent 源码深度剖析十三 -- libevent 信号处理注意点 前面讲到了 libevent 实现多线程的方法,然而在多线程的环境中注册信号事件,还是有一些情况需要小心处理,那就是不能在多 ...

  8. libevent源码深度剖析九

    libevent源码深度剖析九 --集成定时器事件 张亮 现在再来详细分析libevent中I/O事件和Timer事件的集成,与Signal相比,Timer事件的集成会直观和简单很多.Libevent ...

  9. libevent源码深度剖析六

    libevent源码深度剖析六 --初见事件处理框架 张亮 前面已经对libevent的事件处理框架和event结构体做了描述,现在是时候剖析libevent对事件的详细处理流程了,本节将分析libe ...

  10. libevent源码深度剖析五

    libevent源码深度剖析五 --libevent的核心:事件event张亮 对事件处理流程有了高层的认识后,本节将详细介绍libevent的核心结构event,以及libevent对event的管 ...

最新文章

  1. 【iOS官方文档翻译】UICollectionView与UICollectionViewFlowLayout
  2. Android mock for循环,Android单元测试(五):依赖注入,将mock方便的用起来
  3. linux下的git 编辑器,vim - 如何让Git使用我选择的编辑器进行提交?
  4. [Linux/Ubuntu] vi/vim 使用方法讲解
  5. 头脑仅仅是一个实验室
  6. 【使用技巧】【图像编辑和处理】将多幅图片放到一块方便对比
  7. mongodb的用法
  8. wine 运行QQ的问题
  9. Maxwell安装与配置
  10. C#——NotifyICON的使用
  11. pip 卸载包失败的文件夹处理
  12. 什么是Java(什么?Java?)
  13. CPU位数和DDR位宽
  14. Sigfox融资1.5亿欧元扩展LPWA网络
  15. Eclipse/Myeclipse自定义JSP模板
  16. 小米oj 找到第 N 个数字 II
  17. 计算机录入大赛,计算机文字录入PPT幻灯片制作大赛策划书
  18. 《黑客与画家》读书笔记(一)
  19. 23年5月高项学习笔记15 —— 配置与变更
  20. Winscp无法连接SFTP服务器

热门文章

  1. 面试、笔试中常用的SQL语句(数据库知识必杀)一共50个!!!
  2. 回味手写三层-增删改查
  3. Android编码规范05
  4. .net面试中常被面试官问到的问题
  5. 运用Unity结合PolicyInjection实现拦截器[结合操作日志实例]
  6. C# 程序中使用 SQLite 数据库
  7. VSA Cluster中小企业无SAN环境解决方案
  8. CountDownLatch理解
  9. hash 图像检索方法汇总
  10. leetcode_684. Redundant Connection