`
luozhaoyu
  • 浏览: 343316 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

libevent0.1&0.2源码理解(一)类型与变量

阅读更多
修改记录:
3-28 初稿
3-39 补充了全局变量说明,补充了0.2的内容

libevent是一个高性能的异步处理函数库。使用libevent库的著名软件有chromium、memcached、Tor等等。
网上libevent的中文文档不是很少,其中张亮写的libevent源码分析写得不错。但是当时的1.4版本篇幅还是过长,本文将浅析libevent的0.1及0.2版本,其中体现了libevent最基础的东西,希望能给诸位一个快速的印象。
还是请注意,现在的libevent2与之前的版本很不一样了。

基本类型
libevent最基础的数据类型是event
struct event {
	TAILQ_ENTRY (event) ev_read_next;
	TAILQ_ENTRY (event) ev_write_next;
	TAILQ_ENTRY (event) ev_timeout_next;
	TAILQ_ENTRY (event) ev_add_next;

	int ev_fd; //包含的socket套接字,是event的核心
	short ev_events; //对应的事件集

	struct timeval ev_timeout; //定时器

	void (*ev_callback)(int, short, void *arg); //对应的回调函数
	void *ev_arg; //参数

	int ev_flags; //标志
};

这里最难理解的就是TAILQ_ENTRY了,这个宏是定义在queue.h文件当中
#define TAILQ_ENTRY(type)						\
struct {								\
	struct type *tqe_next;	/* next element */			\
	struct type **tqe_prev;	/* address of previous next element */	\
}

从宏定义可以看出,此结构体没有名字,所以只能在某一个结构体中被使用(这里就是struct event)
这里定义的是一个tail queue的结构,该结构比较好玩,本人之前把它误想成双向链表了,但仔细看看,似乎还不全是。
tqe_next很常见,指向下一个元素
tqe_prev是 前面一个元素当中 指向下一个元素的 那个指针的指针……所以有2个星号。(在写本文之时,我还不清楚为什么要这么绕)

回过头来看,
ev_read_next可以用来找到在队列中下一个可以准备读的套接字
ev_write_next可以用来找到在队列中下一个可以准备写的套接字
ev_timeout_next可以用来找到在队列中下一个定时器
ev_add_next可以用来找到在队列中下一个需要处理的事件

0.2版本中增加了提供多平台网络编程的包装结构
struct eventop {
	char *name;
	void *(*init)(void);
	int (*add)(void *, struct event *); //事件增加的回调函数,下同,全字面意思不解释
	int (*del)(void *, struct event *);
	int (*recalc)(void *, int);
	int (*dispatch)(void *, struct timeval *);
};



全局变量
刚才说到队列,可是在使用库的时候,哪来得队列呢?
这是在event.c文件中已经定义的全局变量
TAILQ_HEAD (timeout_list, event) timequeue; //定时器队列的头结点
TAILQ_HEAD (event_wlist, event) writequeue; //写队列的头结点
TAILQ_HEAD (event_rlist, event) readqueue; //读队列的头结点
TAILQ_HEAD (event_ilist, event) addqueue; //待处理队列的头结点
其中timequeue这个定时器队列是按照结构体timeval从小到大的顺序进行排列的,后面增加事件时会提到。

int event_inloop = 0; //锁。用于判断程序此时是否在轮询之中
int event_fds;		/* Highest fd in fd set */
int event_fdsz; //size。用于计算event_fds总共要用多大空间
fd_set *event_readset; //对应于select的readset
fd_set *event_writeset; //对应于select的writeset


0.2版本中增加的全局变量
struct eventop *evsel;
void *evbase;

event.c当中存在一个全局数组struct eventop *eventops[]用于指示系统当中有以下哪些网络处理函数可使用:kqueue, epoll, poll, select等等。
然后程序会选择一个传给evsel
evsel会调用初始化函数返回一个指向网络处理函数结构体的指针给evbase。
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics