libevent源码深度剖析三

前言

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

基本应用场景

基本应用场景也是使用libevnet的基本流程,下面来考虑一个最简单的场景,使用livevent设置定时器,应用程序只需要执行下面几个简单的步骤即可。

  1. 首先初始化libevent库,并保存返回的指针
struct event_base * base = event_init();

实际上这一步相当于初始化一个Reactor实例;在初始化libevent后,就可以注册事件了。

  1. 初始化事件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事件集合,这需要应用程序自行管理;

  1. 设置event从属的event_base
event_base_set(base, &ev);

这一步相当于指明event要注册到哪个event_base实例上;

  1. 是正式的添加事件的时候了
event_add(&ev, timeout);

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

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

实例代码

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

struct event ev;
struct timeval tv;
void time_cb(int fd, short event, void *argc)
{
    printf("timer wakeup/n");
    event_add(&ev, &tv); // reschedule timer
}
int main()
{
    struct event_base *base = event_init();
    tv.tv_sec = 10; // 10s period
    tv.tv_usec = 0;
    evtimer_set(&ev, time_cb, NULL);
    event_add(&ev, &tv);
    event_base_dispatch(base);
}

事件处理流程

当应用程序向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将所有的就绪事件,放入到激活链表中;
然后对激活链表中的事件,调用事件的回调函数执行事件处理;
在这里插入图片描述

小结

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

相关博客

libevent源码剖析

转自:libevent源码深度剖析三

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
libevent是一个事件驱动的网络编程库,适用于高并发的网络应用。通过深度剖析libevent源码,我们可以更好地理解其工作原理和实现机制。 首先,在下载libevent源码之前,我们需要确认所需的版本和平台兼容性,这样可以避免不必要的错误和兼容性问题。 在深度剖析libevent源码时,我们可以从以下几个方面入手: 1. 事件循环机制:libevent基于事件循环机制实现事件的响应和处理。源码中会包含事件循环的实现细节,如事件的注册、删除、触发等操作。研究这些实现可以帮助我们理解事件驱动模型的运行机制。 2. IO多路复用:libevent底层使用了IO多路复用技术,可以同时处理多个网络连接,提高并发处理能力。源码中会涉及到IO多路复用的实现细节,如select、epoll等。了解这些实现可以帮助我们深入理解libevent是如何高效地管理和处理网络连接的。 3. 常用数据结构和算法:libevent源码中使用了一些常用的数据结构和算法,如链表、堆等。通过研究这些数据结构和算法的实现,可以提高我们对libevent整体架构的理解。 4. 错误处理和调试机制:源码中通常也会包含一些错误处理和调试机制,可以帮助我们排查和解决问题。了解这些机制可以提高我们在使用libevent时的调试和排错能力。 总之,深度剖析libevent源码可以帮助我们更好地理解其工作原理和实现机制,从而更好地使用和调优libevent,提高网络应用的性能和并发处理能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值