文章目录
  1. evcb_active_next
  2. evcb_flags
  3. evcb_closure
  4. ev_timeout_pos
  5. ev_

event结构体封装了句柄、事件类型、回调函数以及其他必要的标志与数据。event结构体定义如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
引用方式: #include <event.h>
evcb_active_next: 详见evcb_active_next段
evcb_flags: 详见evcb_flags段
evcb_pri: 指定事件处理器优先级(值越小优先级越高)
evcb_closure: 详见evcb_closure段
evcb_cb_union: 回调函数
evcb_arg: 回调函数的参数
*/

struct event_callback {
TAILQ_ENTRY(event_callback) evcb_active_next;
short evcb_flags;
ev_uint8_t evcb_pri; /* smaller numbers are higher priority */
ev_uint8_t evcb_closure;
/* allows us to adopt for different types of events */
union {
void (*evcb_callback)(evutil_socket_t, short, void *);
void (*evcb_selfcb)(struct event_callback *, void *);
void (*evcb_evfinalize)(struct event *, void *);
void (*evcb_cbfinalize)(struct event_callback *, void *);
} evcb_cb_union;
void *evcb_arg;
};

/*
引用方式: #include <event.h>
ev_evcallback: 回调函数相关标志与数据(详见结构体event_callback注释)
ev_timeout_pos: 详见ev_timeout_pos段
ev_fd: 与事件处理器关联的句柄; 对于I/O事件处理器: 文件描述符值 || 对于信号事件处理器: 信号值
ev_base: 事件处理器从属的event_base实例
ev_: 详见ev_段
ev_events: 事件类型; 取值可以是event_new中介绍的各种事件类型的按位或(除了互斥的事件类型,如读写事件与信号事件不能同时设置)
ev_res: 记录当前激活事件的类型
ev_timeout: 指定定时器的超时值(仅对定时器有效)
*/

struct event {
struct event_callback ev_evcallback;
/* 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 {
LIST_ENTRY (event) ev_io_next;
struct timeval ev_timeout;
} ev_io;
/* used by signal events */
struct {
LIST_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 */
struct timeval ev_timeout;
};

以下是一些数据结构的详解。

evcb_active_next

所有被激活的事件处理器通过evcb_active_next成员串联成一个尾队列,即活动事件队列。

活动事件队列不止一个,不同优先级(evcb_pri成员)的事件处理器被激活后将被插入不同的活动事件队列中。

在事件循环中,Reactor将按优先级由高到低遍历所有活动事件队列,并依次处理其中的事件处理器。

evcb_flags

事件标志。有如下可选值。

  • EVLIST_TIMEOUT。事件处理器从属于通用定时器队列/时间堆;
  • EVLIST_INSERTED。事件处理器从属于注册事件队列;
  • EVLIST_SIGNAL。此标志未使用;
  • EVLIST_ACTIVE。事件处理器从属于活动事件队列;
  • EVLIST_INTERNAL。用于内部使用;
  • EVLIST_INIT。事件处理器已被初始化;
  • EVLIST_ACTIVE_LATER。
  • EVLIST_FINALIZING。
  • EVLIST_ALL。定义所有标志;

evcb_closure

指定event_base执行事件处理器的回调函数时的行为。有如下可选值。

  • EV_CLOSURE_EVENT。默认行为,调用evcb_callback回调函数;
  • EV_CLOSURE_EVENT_SIGNAL。执行信号事件处理器的回调函数时,调用ev_signal.ev_ncalls次回调函数;
  • EV_CLOSURE_EVENT_PERSIST。执行完回调函数后,再次将事件处理器加入注册事件队列;
  • EV_CLOSURE_CB_SELF。调用evcb_selfcb回调函数;
  • EV_CLOSURE_CB_FINALIZE。正在完成的回调,使用evcb_cbfinalize回调函数;
  • EV_CLOSURE_EVENT_FINALIZE。正在完成的回调,使用evcb_evfinalize回调函数;
  • EV_CLOSURE_EVENT_FINALIZE_FREE。正在完成的回调,且之后事件处理器将被释放;使用evcb_evfinalize回调函数;

ev_timeout_pos

定时器通常由时间堆来管理,但一些情况下使用简单的链表来管理效率更高。2.0版本的libevent引入了所谓”通用定时器”的概念,这些定时器存储在尾队列中,记为通用定时器队列。

其中ev_next_with_common_timeout成员指定通用定时器情况下该定时器在通用定时器队列中的位置;min_heap_idx成员指定其他定时器情况下该定时器在时间堆中的位置。

一个定时器是否为通用定时器取决于其超时值大小,通过event.c中的is_common_timeout函数判断。

ev_

所有具有相同文件描述符的I/O事件处理器通过ev_io.ev_io_next成员串联成一个尾队列,即I/O事件队列;所有具有相同信号值的信号事件处理器通过ev_signal.ev_signal_next成员串联成一个尾队列,即信号事件队列。

ev_signal.ev_ncalls成员指定信号事件发生后,Reactor需要执行多少次该事件对应的事件处理器中的回调函数。ev_signal.ev_pncalls成员要么指向ev_signal.ev_ncalls,要么为空。