libevent项目分析(二) -- 例程分析
来源:互联网 发布:澳洲网络运营商 编辑:程序博客网 时间:2024/06/05 14:10
初始化
libevent库的使用是从对event_base结构初始化开始的,前面例程中使用的方法是不带任何参数的event_base_new函数,类似的还有event_init函数。前者创建并初始化了一个默认的event_config结构,然后调用event_base_new_with_config函数;而后者更加简单,用了一个NULL做为参数调用event_base_new_with_config函数。所以可以理解libevent库的初始化核心是event_base_new_with_config函数,对该函数的分析留给后面,这次不打算分析到具体函数的实现 :)
事件定义
libevent库实现的就是事件监听和驱动机制,该库中对事件的定义是event结构。该结构不是很复杂,但比较重要,这里列出几个比较重要的成员变量
1,双向事件链表
TAILQ_ENTRY(event) ev_active_next;
TAILQ_ENTRY(event) ev_next;
其中TAILQ_ENTRY宏在event2/event_struct.h文件中定义如下
/* Fix so that people don't have to run with <sys/queue.h> */
#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 /* !TAILQ_ENTRY */
2,事件对应的句柄
SOCKET事件句柄
evutil_socket_t ev_fd;
IO事件句柄
/* 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;
PS : 1,IO事件句柄与信号事件句柄通过union方式定义;2,定时器事件是靠时间差比较来监听,所以这里没有定时器事件的句柄
3,event_base指针: 通过该成员变量,event事件可以知道自己注册在哪个event_base
struct event_base *ev_base;
4,event属性 :
short ev_events;
/**
* @name event flags
*
* Flags to pass to event_new(), event_assign(), event_pending(), and
* anything else with an argument of the form "short events"
*/
/**@{*/
/** Indicates that a timeout has occurred. It's not necessary to pass
* this flag to event_for new()/event_assign() to get a timeout. */
#define EV_TIMEOUT 0x01
/** Wait for a socket or FD to become readable */
#define EV_READ 0x02
/** Wait for a socket or FD to become writeable */
#define EV_WRITE 0x04
/** Wait for a POSIX signal to be raised*/
#define EV_SIGNAL 0x08
/**
* Persistent event: won't get removed automatically when activated.
*
* When a persistent event with a timeout becomes activated, its timeout
* is reset to 0.
*/
#define EV_PERSIST 0x10
/** Select edge-triggered behavior, if supported by the backend. */
#define EV_ET 0x20
/**@}*/
5,event标识:
short ev_flags;
#define EVLIST_TIMEOUT0x01
#define EVLIST_INSERTED 0x02
#define EVLIST_SIGNAL 0x04
#define EVLIST_ACTIVE 0x08
#define EVLIST_INTERNAL 0x10
#define EVLIST_INIT 0x80
6,事件优先级:数值越小,优先级越高,默认为适中
ev_uint8_t ev_pri;
7,事件对应的回调函数指针及参数
/* allows us to adopt for different types of events */
void (*ev_callback)(evutil_socket_t, short, void *arg);
void *ev_arg;
事件初始化
和event相关的函数有下面几个:
event创建:event_new
event设置:event_set,event_assign
event释放: event_free
其中最核心的是event_assign函数,这里分析其参数的意义,说明事件关注的方面
int event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg)
struct event *ev :event事件指针
struct event_base *base : event_base指针
evutil_socket_t fd : 套接口句柄,其他类型事件可以赋值-1
short events : 事件的属性
void (*callback)(evutil_socket_t, short, void *) : 事件处理回调函数指针
void *arg : 事件处理回调函数参数
注册事件
例程中通过event_add函数注册一个定时事件,实际上注册事件是由event_add_internal函数实现,event_add函数会为调用event_add_internal函数增加锁保护。event_add_internal函数通过事件的ev_events属性判断事件类型,从而调用不同函数实现事件注册
对于IO事件的注册由evmap_io_add函数实现
int evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev)
PS :相关的其他几个和IO事件操作函数evmap_io_init,evmap_io_del,evmap_io_active
对于Signal事件的注册由evmap_signal_add函数实现
int evmap_signal_add(struct event_base *base, int sig, struct event *ev)
PS :相关的其他几个和Signal事件操作函数evmap_signal_init,evmap_signal_del,evmap_signal_active
对于定时器事件的注册由event_add_internal参数中的const struct timeval *tv参数决定???
事件驱动
例程通过调用event_base_dispatch函数驱动事件,实际上事件驱动机制是由event_base_loop函数封装实现的。这里需注意event_base结构的成员变量const struct eventop *evsel,这个指针指向eventops数组中的一个元素,根据宏定义选择不同的事件监听机制(例如poll/select/epoll等),这里先不细说。
事件回调
在源代码中一时还没发现是在哪里回调了事件处理函数,换一种途径,通过gdb在例程的时间事件处理函数设置断点跟踪,可以发现事件处理函数是由event_process_active_single_queue函数调用的,关系如下:
(gdb) where
#0 handle_timer (fd=-1, event=1, arg=0xbffff054) at mytimer.c:19
#1 0x0011e248 in event_process_active_single_queue (base=0x804a008, flags=0)
at event.c:1340
#2 event_process_active (base=0x804a008, flags=0) at event.c:1407
#3 event_base_loop (base=0x804a008, flags=0) at event.c:1604
#4 0x0011f255 in event_base_dispatch (event_base=0x804a008) at event.c:1435
#5 0x080486c4 in main (argc=1, argv=0xbffff164) at mytimer.c:43
- libevent项目分析(二) -- 例程分析
- libevent项目分析(一) -- 准备阶段 .例程分析
- Libevent源码分析(二)--- 时间管理
- libevent项目分析(一) -- 准备阶段
- libevent项目分析(四) -- 事件驱动
- libevent项目分析 (二) -- I/O多路复用基础 .事件驱动
- 多标识AR例程分析(二)
- 多标识AR例程分析(二)
- Libevent-2.1.8源码分析——event_base(二)
- Libevent分析
- Libevent源代码分析笔记二,初始化
- libevent源代码分析——event_dispatch() (二)
- Libevent 源码分析(原创)
- libevent源码分析(1)
- 实战项目分析(二)
- opencv例程分析(1)
- opencv例程分析(2)
- opencv例程分析(3)
- 指针详解
- web项目中Log4j不输出到文件问题
- 《一线架构师》 - 书摘精要
- ASP.NET弹出对话框几种基本方法VB.NET
- Struts 2读书笔记-----Action访问Servlet API
- libevent项目分析(二) -- 例程分析
- WebService 服务可以返回任意类型
- Vim 复制粘贴探秘
- zoj 1610 Count the Colors
- XmlDocument/XmlTextWriter
- win7_fedora 双系统安装方法
- 数据库中间件技术的研究与应用
- 程序员技术练级攻略
- 倒序取字符串函数