(五)struct event结构体

本文详细介绍了libevent中的核心结构体struct event,包括其在事件驱动模型中的作用、结构体成员、事件类型、事件状态、事件管理方式,以及回调函数的使用。重点讨论了event如何按优先级管理和激活事件,并与event_base的关系。

前言

之前说到过libevent是基于事件驱动模型的网络库,其中的事件,就是event,它的确算是libevent中最核心的部分,而上一节说到的event_base其实算是驱动部分,负责事件的各种处理。它们之间的关系是,一个event_base对应多个event
下面主要讲解的是struct event结构体,位于event.h

struct event

struct event {
    /* 尾队列节点指针 用于保存所有注册了的I/O以及signal事件 以及激活的事件(其实libevent中的尾队列本质上就是一个双向链表)*/
    TAILQ_ENTRY (event) ev_next;    //已注册I/O事件链表
    TAILQ_ENTRY (event) ev_active_next; //所有激活了的事件链表,通过遍历该链表进行调度
    TAILQ_ENTRY (event) ev_signal_next; //已注册signal事件链表

    unsigned int min_heap_idx;  /* for managing timeouts */

    struct event_base *ev_base; //该事件所属的反应堆实例

    int ev_fd;  //对于I/O事件,是绑定的文件描述符。对于signal事件,是绑定的信号
    short ev_events;    /* 事件的类型 */
    short ev_ncalls;    //事件就绪执行时,调用ev_callback的次数
    short *ev_pncalls;  /* Allows deletes in callback */

    struct timeval ev_timeout; //定时的时长

    int ev_pri; //优先级 smaller numbers are higher priority

    /* event的回调函数,被ev_base调用
     * int参数代表ev_fd
     * short参数代表事件的类型,即ev_events
     * void *arg对应ev_arg
     */

    void (*ev_callback)(int, short, void *arg);
    void *ev_arg;

    int ev_res; //当前激活事件的类型 /* result passed to event callback */
    int ev_flags; //表明当前event的状态
};

额外注意

有以下几点进行补充说明:
1. TAILQ_ENTRY()是一个宏,原型如下:

#define TAILQ_ENTRY(type)                       \
struct {                                \
     struct type *tqe_next; /* next element */          \
     struct type **tqe_prev;    /* address of previous next element */  \
 }

如你所见,它其实是一个尾队列结点。它的第一个成员tqe_next指向下一个元素,第二个成员tqe_prev是前一个元素的下个元素的地址。这样做的好处是,删除元素时不必遍历整个链表,同时也支持方向遍历。具体的操作等后面遇到了再讲。
2.
事件类型(short ev_events)有如下4种:

/* 定时事件 */
#define EV_TIMEOUT  0x01

/* I/O事件 */
#define EV_READ     0x02
#define EV_WRITE    0x04

/* 信号事件 */
#define EV_SIGNAL   0x08

/* 辅助选项:表明是永久(持续的)事件 */
#define EV_PERSIST  0x10    /* Persistant event */

这些事件可以进行|操作,即一个事件可以是多种类型的,不过signal类型不能和I/O类型同为同一事件。
3. event的状态(int ev_flags)有如下几种:

#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 已被初始化

4. 通过查看该结构体的成员,我们不难发现,libevent将事件分为了I/O事件信号事件定时事件这几类,并且管理注册事件的时候分了不同的链表来管理,已经激活等待调度的事件也有一个专门的链表来管理。
5. 还有一个优先级的概念,前面我们在介绍event_base结构体时,有个成员是activequeues,它专门用来按优先级管理已经激活(就绪)的事件。于是,每当有event被激活时,libevent就会把它移入activequeues[event->ev_pri]中。
6. 接着便是回调函数,event负责保管回调函数指针,真正来调用的是事件主循环中的event_process_active函数。

小结

OK,我们当前看了libevent中最主要的两个结构体:struct eventstruct event_base,了解到event将事件分类管理,里面存放了重要的回调函数指针并且知道了它和event_base的关系(多对一)。下面我们可以忽略信号和定时部分,看一看event_baseevent之间是如何协调的,这对我们理解eventevent_base很有好处。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值