libevent源码深度剖析三

——libevent基本使用场景和事件流程
张亮

1 前言

学习源代码该从哪里入手?我觉得从程序的基本使用场景和代码的整体处理流程入手是个不错的方法,至少从个人的经验上讲,用此方法分析libevent是比较有效的。

2 基本应用场景

基本应用场景也是使用libevnet的基本流程,下面来考虑一个最简单的场景,使用livevent设置定时器,应用程序只需要执行下面几个简单的步骤即可。
1)首先初始化libevent库,并保存返回的指针
struct event_base * base = event_init();
实际上这一步相当于初始化一个Reactor实例;在初始化libevent后,就可以注册事件了。

2)初始化事件event,设置回调函数和关注的事件
evtimer_set(&ev, timer_cb, NULL);
事实上这等价于调用event_set(&ev, -1, 0, timer_cb, NULL);
event_set的函数原型是:
void event_set(struct event *ev, int fd, short event, void (*cb)(int, short, void *), void *arg)
ev:执行要初始化的event对象;
fd:该event绑定的“句柄”,对于信号事件,它就是关注的信号;
event:在该fd上关注的事件类型,它可以是EV_READ, EV_WRITE, EV_SIGNAL;
cb:这是一个函数指针,当fd上的事件event发生时,调用该函数执行处理,它有三个参数,调用时由event_base负责传入,按顺序,实际上就是event_set时的fd, event和arg;
arg:传递给cb函数指针的参数;
由于定时事件不需要fd,并且定时事件是根据添加时(event_add)的超时值设定的,因此这里event也不需要设置。
这一步相当于初始化一个event handler,在libevent中事件类型保存在event结构体中。
注意:libevent并不会管理event事件集合,这需要应用程序自行管理;

3)设置event从属的event_base
event_base_set(base, &ev);    
这一步相当于指明event要注册到哪个event_base实例上;

4)是正式的添加事件的时候了
event_add(&ev, timeout);
基本信息都已设置完成,只要简单的调用event_add()函数即可完成,其中timeout是定时值;
这一步相当于调用Reactor::register_handler()函数注册事件。

5)程序进入无限循环,等待就绪事件并执行事件处理
event_base_dispatch(base);

3 实例代码

上面例子的程序代码如下所示

[cpp] view plaincopy
  1. struct event ev;
  2. struct timeval tv;
  3. void time_cb(int fd, short event, void *argc)
  4. {
  5. printf("timer wakeup/n");
  6. event_add(&ev, &tv); // reschedule timer
  7. }
  8. int main()
  9. {
  10. struct event_base *base = event_init();
  11. tv.tv_sec = 10; // 10s period
  12. tv.tv_usec = 0;
  13. evtimer_set(&ev, time_cb, NULL);
  14. event_add(&ev, &tv);
  15. event_base_dispatch(base);
  16. }

4 事件处理流程

当应用程序向libevent注册一个事件后,libevent内部是怎么样进行处理的呢?下面的图就给出了这一基本流程。
1)    首先应用程序准备并初始化event,设置好事件类型和回调函数;这对应于前面第步骤2和3;
2)    向libevent添加该事件event。对于定时事件,libevent使用一个小根堆管理,key为超时时间;对于Signal和I/O事件,libevent将其放入到等待链表(wait list)中,这是一个双向链表结构;
3)    程序调用event_base_dispatch()系列函数进入无限循环,等待事件,以select()函数为例;每次循环前libevent会检查定时事件的最小超时时间tv,根据tv设置select()的最大等待时间,以便于后面及时处理超时事件;
当select()返回后,首先检查超时事件,然后检查I/O事件;
Libevent将所有的就绪事件,放入到激活链表中;
然后对激活链表中的事件,调用事件的回调函数执行事件处理;
 

5 小结

本节介绍了libevent的简单实用场景,并旋风般的介绍了libevent的事件处理流程,读者应该对libevent有了基本的印象,下面将会详细介绍libevent的事件管理框架(Reactor模式中的Reactor框架)做详细的介绍,在此之前会对源代码文件做简单的分类。

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

  1. libevent源码深度剖析

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

  2. libevent源码深度剖析十一

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

  3. libevent源码深度剖析八

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

  4. libevent源码深度剖析十

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

  5. libevent源码深度剖析一

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

  6. libevent 源码深度剖析十三

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

  7. libevent源码深度剖析十二

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

  8. libevent源码深度剖析九

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

  9. libevent源码深度剖析六

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

最新文章

  1. 《软件测试经验与教训》之二——测试内容先后顺序
  2. mysql 开启守护进程_[求助]Linux上MySQL Server 5.6 安装后无法启动守护进程
  3. Android面试总结经
  4. DATEDIFF() 函数返回两个日期之间的天数
  5. 从软件工程的角度比较Swift、Go和Julia,我有了这些发现
  6. Android反编译分析工具
  7. Slider 滑动条效果
  8. 北理工java分析题_2020春北理工《Java技术与应用》在线作业-1(参考)
  9. Go语言编程笔记1:Hello World
  10. 【CF335E】 Counting Skyscrapers(期望)
  11. 某云盘下载工具(IDM,Aria2)速度测试
  12. open judge 1.6.4
  13. JXL开发Excel文档中文教程
  14. 红米k30支持html,红米k30支持多大的快充
  15. idea配置git仓库(idea配置git)详细
  16. boss直聘账号异常登不上_python爬虫Scrapy:爬取boss数据
  17. AliPay - Java支付宝接口开发(三)
  18. 如何搭建windows server服务器
  19. 互联网的一些小知识点
  20. Java中哪些集合是有序的?

热门文章

  1. 在linux中 与 的区别,在linux中,和, |和|| , 与 的区别
  2. ubantu安装mysql卡住_ubuntu安装mysql遇到的问题
  3. python给列表的每一项都加上特定的字符串
  4. pyqt5 qscrollarea到达_PyQt5如何用QPainter在QScrollArea上画线?
  5. 伪静态php空间,Win空间上如何实现WordPress博客的完美伪静态
  6. js正则匹配闭合标签_正则表达式匹配封闭html标签
  7. 06jQuery-06-AJAX
  8. How to Leak a Context: Handlers Inner Classes
  9. java蓝桥杯算法训练 奇偶判断
  10. bootstrap table相关操作