libevent源码分析-event

  • event结构
  • event相关接口
  • Libevent对event的管理

event结构

event是Reactor模式中的最重要的组件。它包含了了一个句柄fd,并设置监听这个句柄上的哪些事件(读/写等),设置了对应的函数指针,在事件到来时,回调函数指针来处理事件。
先看一下event的结构。它位于include/event2/event_struct.h中

struct event {
    TAILQ_ENTRY(event) ev_active_next;
    TAILQ_ENTRY(event) ev_next;
    /* for managing timeouts */
    union {
        TAILQ_ENTRY(event) ev_next_with_common_timeout;
        int min_heap_idx;
    } ev_timeout_pos;
    evutil_socket_t ev_fd;

    struct event_base *ev_base;

    union {
        /* used for io events */
        struct {
            TAILQ_ENTRY(event) ev_io_next;
            struct timeval ev_timeout;
        } ev_io;

        /* used by signal events */
        struct {
            TAILQ_ENTRY(event) ev_signal_next;
            short ev_ncalls;
            /* Allows deletes in callback */
            short *ev_pncalls;
        } ev_signal;
    } _ev;

    short ev_events;
    short ev_res;       /* result passed to event callback */
    short ev_flags;
    ev_uint8_t ev_pri;  /* smaller numbers are higher priority */
    ev_uint8_t ev_closure;
    struct timeval ev_timeout;

    /* allows us to adopt for different types of events */
    void (*ev_callback)(evutil_socket_t, short, void *arg);
    void *ev_arg;
};

TAILQ_ENTRY是宏定义,展开后为双向链表中的指针结点。

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

这个指针信息用来管理event事件。event事件在Reactor中,用链表存储。
ev_active_next是激活事件在激活事件链表中的位置。Reactor中有激活事件列表,程序会遍历这个列表,执行响应的处理程序。
ev_next保存了当前事件在注册链表中的位置。
ev_timeout_pos是union,它是定时器或在超时链表中的位置。
ev_fd时event管理的fd,可以时socket或signal。
ev_base是event所在的Reactor。
_ev是个union,event可能是IO事件,也可能时signal事件。用一个union表示,节省了空间。
ev_events表明监听事件的类型。可以是以下事件

#define EV_TIMEOUT 0x01 //定时器事件
#define EV_READ 0x02 //IO读事件
#define EV_WRITE 0x04 //IO写事件
#define EV_SIGNAL 0x08 //信号事件
#define EV_PERSIST 0x10 //永久事件

ev_flags表示当前event的状态,值如下

#define EVLIST_TIMEOUT 0x01 //在time堆中
#define EVLIST_INSERTED 0x02 //已经添加到事件列表中
#define EVLIST_SIGNAL 0x04 //
#define EVLIST_ACTIVE 0x08 //在激活链表中
#define EVLIST_INTERNAL 0x10 
#define EVLIST_INIT 0x80 //已经初始化

ev_pri表示优先级。数字越小,优先级越高,可以调用函数设置

int event_priority_set(struct event *ev, int pri)

ev_closure根据其类型来调用不同回调函数。
ev_callback是event的回调函数。三个参数分别为ev_fdev_eventsev_arg

event相关接口

有关event的接口定义在event.c中。在前面程序中用到了

event_set(&listenEvent, sock, EV_READ|EV_PERSIST, handleAccept, NULL);
event_base_set(base, &listenEvent);
event_add(&listenEvent, NULL);

其中

void
event_set(struct event *ev, evutil_socket_t fd, short events,
      void (*callback)(evutil_socket_t, short, void *), void *arg)

功能为设置event的参数。
ev表示event事件。
fd表示和事件相关联的fd。
callback是函数指针,表示事件处理程序。
arg为ev_arg的值。

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

功能为将event和Reactor关联起来。
base是event所在的Reactor。

int
event_add(struct event *ev, const struct timeval *tv)

功能为将event添加到Reactor中。
tv是超时时间。

Libevent对event的管理

libevent源码分析-event_第1张图片
借助别人博客的图,形象的看一下Reactor中,怎么管理event。在反应堆event_base中有相应的链表和堆,来管理event事件。不同的事件对应不同指针/字段,IO事件对应ev_next,信号事件对应ev_signal_next,定时器事件对应min_head_idx,激活后的事件对应ev_active_next。当事件激活后,把事件转移到list[priority]队列,之后对事件一一处理。

参考:
深入理解TAILQ队列

linux内核分析–内核中的数据结构之双链表(一)

libevent源码深度剖析五——libevent的核心:事件event

http://www.wangafu.net/~nickm/libevent-2.0/doxygen/html/structevent.html

你可能感兴趣的:(libevent,event)