libevent源码深度剖析五

前言

对事件处理流程有了高层的认识后,本节将详细介绍libevent的核心结构event,以及libevent对event的管理。

libevent的核心-event

Libevent是基于事件驱动(event-driven)的,从名字也可以看到event是整个库的核心。event就是Reactor框架中的事件处理程序组件;它提供了函数接口,供Reactor在事件发生时调用,以执行相应的事件处理,通常它会绑定一个有效的句柄。
首先给出event结构体的声明,它位于event.h文件中:

struct event {
 TAILQ_ENTRY (event) ev_next;
 TAILQ_ENTRY (event) ev_active_next;
 TAILQ_ENTRY (event) ev_signal_next;
 unsigned int min_heap_idx; /* for managing timeouts */
 struct event_base *ev_base;
 int ev_fd;
 short ev_events;
 short ev_ncalls;
 short *ev_pncalls; /* Allows deletes in callback */
 struct timeval ev_timeout;
 int ev_pri;  /* smaller numbers are higher priority */
 void (*ev_callback)(int, short, void *arg);
 void *ev_arg;
 int ev_res;  /* result passed to event callback */
 int ev_flags;
};

下面简单解释一下结构体中各字段的含义。

  1. ev_events:event关注的事件类型,它可以是以下3种类型:
    I/O事件: EV_WRITE和EV_READ
    定时事件:EV_TIMEOUT
    信号: EV_SIGNAL
    辅助选项:EV_PERSIST,表明是一个永久事件
    Libevent中的定义为:
#define EV_TIMEOUT 0x01
#define EV_READ  0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10 /* Persistant event */

可以看出事件类型可以使用“|”运算符进行组合,需要说明的是,信号和I/O事件不能同时设置;
还可以看出libevent使用event结构体将这3种事件的处理统一起来;

  1. ev_next,ev_active_next和ev_signal_next都是双向链表节点指针;它们是libevent对不同事件类型和在不同的时期,对事件的管理时使用到的字段。
    libevent使用双向链表保存所有注册的I/O和Signal事件,ev_next就是该I/O事件在链表中的位置;称此链表为“已注册事件链表”;
    同样ev_signal_next就是signal事件在signal事件链表中的位置;
    ev_active_next:libevent将所有的激活事件放入到链表active list中,然后遍历active list执行调度,ev_active_next就指明了event在active list中的位置;

  2. min_heap_idx和ev_timeout,如果是timeout事件,它们是event在小根堆中的索引和超时值,libevent使用小根堆来管理定时事件,这将在后面定时事件处理时专门讲解

  3. ev_base该事件所属的反应堆实例,这是一个event_base结构体,下一节将会详细讲解;

  4. ev_fd,对于I/O事件,是绑定的文件描述符;对于signal事件,是绑定的信号;

  5. ev_callback,event的回调函数,被ev_base调用,执行事件处理程序,这是一个函数指针,原型为:

void (*ev_callback)(int fd, short events, void *arg)

其中参数fd对应于ev_fd;events对应于ev_events;arg对应于ev_arg;

  1. ev_arg:void*,表明可以是任意类型的数据,在设置event时指定;

  2. eb_flags:libevent用于标记event信息的字段,表明其当前的状态,可能的值有:

#define EVLIST_TIMEOUT 0x01 // event在time堆中
#define EVLIST_INSERTED 0x02 // event在已注册事件链表中
#define EVLIST_SIGNAL 0x04 // 未见使用
#define EVLIST_ACTIVE 0x08 // event在激活链表中
#define EVLIST_INTERNAL 0x10 // 内部使用标记
#define EVLIST_INIT     0x80 // event已被初始化
  1. ev_ncalls:事件就绪执行时,调用ev_callback的次数,通常为1;

  2. ev_pncalls:指针,通常指向ev_ncalls或者为NULL;

  3. ev_res:记录了当前激活事件的类型;

libevent对event的管理

从event结构体中的3个链表节点指针和一个堆索引出发,大体上也能窥出libevent对event的管理方法了,可以参见下面的示意图:

在这里插入图片描述

每次当有事件event转变为就绪状态时,libevent就会把它移入到active event list[priority]中,其中priority是event的优先级;
接着libevent会根据自己的调度策略选择就绪事件,调用其cb_callback()函数执行事件处理;并根据就绪的句柄和事件类型填充cb_callback函数的参数。

事件设置的接口函数

要向libevent添加一个事件,需要首先设置event对象,这通过调用libevent提供的函数有:event_set(), event_base_set(), event_priority_set()来完成;下面分别进行讲解。

void event_set(struct event *ev, int fd, short events, 
void (*callback)(int, short, void *), void *arg)
  1. 设置事件ev绑定的文件描述符或者信号,对于定时事件,设为-1即可;

  2. 设置事件类型,比如EV_READ|EV_PERSIST, EV_WRITE, EV_SIGNAL等;

  3. 设置事件的回调函数以及参数arg;

  4. 初始化其它字段,比如缺省的event_base和优先级;

int event_base_set(struct event_base *base, struct event *ev)

设置event ev将要注册到的event_base;
libevent有一个全局event_base指针current_base,默认情况下事件ev将被注册到current_base上,使用该函数可以指定不同的event_base;
如果一个进程中存在多个libevent实例,则必须要调用该函数为event设置不同的event_base;

int event_priority_set(struct event *ev, int pri)

设置event ev的优先级,没什么可说的,注意的一点就是:当ev正处于就绪状态时,不能设置,返回-1。

小结

本节讲述了libevent的核心event结构,以及libevent支持的事件类型和libevent对event的管理模型;接下来将会描述libevent的事件处理框架,以及其中使用的重要的结构体event_base;

相关博客

libevent源码剖析

转自:libevent源码深度剖析五

  • 0
    点赞
  • 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、付费专栏及课程。

余额充值