Libevent源码剖析(二)之数据结构
描述Libevent中出现的数据结构:
struct event_base :
事件处理集合
struct event_base {
const struct eventop *evsel; //对struct event对象的操作函数,以指针函数的方式提供
void *evbase; //指向特定数据的指针
struct event_changelist changelist; //记录事件变化的列表,仅由O(1)方式使用
const struct eventop *evsigsel; //对struct event signal对象的处理,以指针函数的方式进行注册
struct evsig_info sig; //实现通用信号处理程序的代码
int virtual_event_count; //虚拟事件数量
int virtual_event_count_max; //最大的活动虚拟事件数量
int event_count; //添加到struct event_base中的事件总数
int event_count_max; //允许添加到struct event_base中的最大的事件数量
int event_count_active; //目前活动的事件总数
int event_count_active_max; //允许的活动事件总数
int event_gotterm; //标志:是否需要在事件处理结束后终止事件循环
int event_break; //标志:是否应该立即终止循环
int event_continue; //标志:是否应该立即启动一个新的事件循环
int event_running_priority; //当前正在运行的事件的优先级
int running_loop; //标志:是否运行event_base_loop函数,以防止可重入调用
int n_deferreds_queued; //标志:防止饥饿的手段
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; \
struct type **tqh_last; \
}
//活动事件管理
struct evcallback_list *activequeues; //活动事件队列,so,evcallback_list很可能是使用了这种方式进行注册的
int nactivequeues; //活动事件队列的长度
struct evcallback_list active_later_queue; //下一次应该激活的事件队列
//超时处理
struct common_timeout_list **common_timeout_queues; //常用的超时队列
int n_common_timeouts; //超时队列中的条目数
int n_common_timeouts_allocated; //超时队列占用的总大小
//管理IO事件与信号事件,我就纳闷了,用红黑树管理不好吗?
struct event_io_map io; //从IO映射中添加的事件
struct event_signal_map sigmap; //从信号映射中添加的事件
struct min_heap timeheap; //使用最小堆将超时事件组织起来
struct timeval tv_cache; //缓存系统时间,避免频繁的系统调用(gettimeofday,虽然说这个函数不陷入系统调用)
struct evutil_monotonic_timer monotonic_timer; //一个空的结构体,用途不明
struct timeval tv_clock_diff; //时钟差异(10ms?20ms?)
time_t last_updated_clock_diff; //最后一次更新事件的记录
//多线程管理
unsigned long th_owner_id; //当前运行loop的thread id
void *th_base_lock; //线程锁,防止对event_base的访问冲突
void *current_event_cond; //条件变量,用于同步事件处理
int current_event_waiters; //阻塞在当前条件变量上的等待线程
struct event_callback *current_event; //正在执行的回调事件
enum event_base_config_flag flags; //这个event_base的配置标志
struct timeval max_dispatch_time; //一次事件循环的最大时间
int max_dispatch_callbacks; //一次事件循环中可以处理的最大 的回调函数
int limit_callbacks_after_prio; //回调函数中的优先级限制
//通知主线程唤醒休息的线程
int is_notify_pending; //标志:struct event_base是否有等待处理的通知
evutil_socket_t th_notify_fd[2]; //与主线程使用管道来进行交互,一般而言,会将主线程阻塞在read fd上
struct event th_notify; //使用事件处理的机制通知主线程,真的是:万物皆事件哇
int (*th_notify_fn)(struct event_base *base); //用于从子线程中唤醒主线程的回调函数
struct evutil_weakrand_state weakrand_seed; //随机数种子
LIST_HEAD(once_event_list, event_once) once_events; //保存目前尚未触发的通过event_once注册的事件
};
struct event
表示一个具体的事件对象,将IO,超时,信号三者统一起来
struct event {
struct event_callback ev_evcallback; //保存事件处理的回调函数,由必要的时候对这个事件进行填充,添加到合适的优先级队列
//管理超时
union {
TAILQ_ENTRY(event) ev_next_with_common_timeout; //我觉着这个有点复杂...直接标记在最小堆中的位置,岂不方便??
int min_heap_idx;
} ev_timeout_pos;
evutil_socket_t ev_fd; //关注的socket fd(int)
struct event_base *ev_base; //依赖的struct event_base对象
union {
struct {
LIST_ENTRY (event) ev_io_next; //在IO事件队列中的位置
struct timeval ev_timeout;
} ev_io; //用于管理IO事件
struct {
LIST_ENTRY (event) ev_signal_next; //在信号事件队列中的位置
short ev_ncalls;
short *ev_pncalls; //允许在回调中删除
} ev_signal; //用于管理超时事件
} ev_;
short ev_events; //关注的事件
short ev_res; //实际发生的事件
struct timeval ev_timeout; //超时时间
};
struct eventop
对struct event_base
的操作
struct eventop {
const char *name; //这个后端的名称
void *(*init)(struct event_base *); //初始化struct event_base对象
int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo); //将struct event对象添加到struct event_base对象中
int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo); //将struct event对象从struct event_base中移除
int (*dispatch)(struct event_base *, struct timeval *); //将控制权提交给事件控制函数
void (*dealloc)(struct event_base *); //清理struct event_base中的对象
int need_reinit; //标志:是否需要在调用fork()函数后重新初始化事件库
enum event_method_feature features; //提供可以支持struct event_method_feature位数组的
size_t fdinfo_len; //为每一个fd维护的信息的长度
};
struct event_changelist
事件变化的列表,仅由O(1)方法使用
struct event_changelist {
struct event_change *changes; //链表
int n_changes;
int changes_size;
};
struct event_change
struct event_change {
evutil_socket_t fd; //Libevent对socketfd,signal,timer的封装,(int)
short old_events; //fd之前上启用的事件
ev_uint8_t read_change; //此次改变发生的读事件
ev_uint8_t write_change; //此次改变发生的写事件
ev_uint8_t close_change; //此次改变发生的关闭事件
};
struct event_method_feature
enum event_method_feature {
EV_FEATURE_ET = 0x01,
EV_FEATURE_O1 = 0x02,
EV_FEATURE_FDS = 0x04,
EV_FEATURE_EARLY_CLOSE = 0x08
};
struct evsig_info
为信号处理函数提供事件
struct evsig_info {
struct event ev_signal; //为信号事件注册的一个struct event对象
evutil_socket_t ev_signal_pair[2]; //使用进程间管道的方式处理信号事件
int ev_signal_added; //判断信号事件是否已经被添加
int ev_n_signals_added; //我们目前正在关注的信号数量
struct sigaction **sh_old; //保存一系列信号处理对象
int sh_old_max; //保存的信号处理对象的个数
}
struct common_timeout_list
处理超时事件
struct common_timeout_list {
struct event_list events; //当前队列中正在等待的事件列表
struct timeval duration; //表示事件的持续时间
struct event timeout_event; //每个队列都为超时时间准备了一个struct event对象
struct event_base *base; //这个struct event对象占用的
};
struct event_io_map
#define event_io_map event_signal_map
struct event_signal_map {
void **entries; //一个二维数据,数组中会维护一些信息
int nentries; //数组中的条目总数
};
struct event_callback
回调函数的封装
#ifndef TAILQ_ENTRY
#define EVENT_DEFINED_TQENTRY_
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
#endif
struct event_callback {
TAILQ_ENTRY(event_callback) evcb_active_next; //回调事件队列中的一个成员
short evcb_flags; //根据flag选择合适的回调函数进行处理
ev_uint8_t evcb_pri; //标志这个事件的优先级
ev_uint8_t evcb_closure;
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; //回调函数使用的参数
};
struct event_config
为struct event_base提供配置对象
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; \
struct type **tqh_last; \
}
struct event_config {
TAILQ_HEAD(event_configq, event_config_entry) entries; //双向链表
int n_cpus_hint; //cpus数量
struct timeval max_dispatch_interval; //最大的循环时间
int max_dispatch_callbacks; //最多的callbacks的调用
int limit_callbacks_after_prio; //优先级限制
enum event_method_feature require_features; //目前struct event_base支持的一些方法
enum event_base_config_flag flags;
};
全局数据结构:eventops
static const struct eventop *eventops[] = {
#ifdef EVENT__HAVE_EVENT_PORTS
&evportops,
#endif
#ifdef EVENT__HAVE_WORKING_KQUEUE
&kqops,
#endif
#ifdef EVENT__HAVE_EPOLL
&epollops,
#endif
#ifdef EVENT__HAVE_DEVPOLL
&devpollops,
#endif
#ifdef EVENT__HAVE_POLL
&pollops,
#endif
#ifdef EVENT__HAVE_SELECT
&selectops,
#endif
#ifdef _WIN32
&win32ops,
#endif
NULL
};