libevent事件(二)---event源码
2017-04-20 16:51
260 查看
libevent事件源码
接下来将学习libevent库中event的源码:首先是event结构体:
struct event { //ev_next ev_active_next等等都是双向链表的指针 //用来管理注册的事件如IO事件 Signal事件 //所有激活的事件将插入到ev_active_next链表中 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; //所关注的字段类型比如:EV_READ EV_WRITE short ev_res; /* result passed to event callback *///记录当前激活事件的类型 short ev_flags;//事件状态,包括:INSERTED ACTIVE等 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;//参数 };
可移植性
我们知道libevent适合于各种平台,其底层的接口如BSD的kqueue还有linux下的epoll等等,那么其可移植性是如何实现的呢?libevent里面定义了一个
eventop结构体,里面就是一堆回调函数接口,libevent会在预编译期选择适当的底层接口。
struct eventop { const char *name; void *(*init)(struct event_base *); int (*add)(void *, struct event *); int (*del)(void *, struct event *); int (*dispatch)(struct event_base *, void *, struct timeval *); void (*dealloc)(struct event_base *, void *); /* set if we need to reinitialize the event base */ int need_reinit; }; static const struct eventop *eventops[] = { #ifdef HAVE_EVENT_PORTS &evportops, #endif #ifdef HAVE_WORKING_KQUEUE &kqops, #endif #ifdef HAVE_EPOLL &epollops, #endif #ifdef HAVE_DEVPOLL &devpollops, #endif #ifdef HAVE_POLL &pollops, #endif #ifdef HAVE_SELECT &selectops, #endif #ifdef WIN32 &win32ops, #endif NULL };
可以看到所有的选项,其实都是在相关的文件中定义,并且在
event.c中
extern一下就可以了,以epoll为例,其实就是对回调的赋值:
//结构体中的回调函数是对epoll三个函数的底层封装 const struct eventop epollops = { "epoll", epoll_init, epoll_add, epoll_del, epoll_dispatch, epoll_dealloc, 1 /* need reinit */ };
最后,在初始化阶段,
event_base结构体成员中,包含一个指向上述结构的指针,并通过该指针直接调用这些回调函数。
例如在
event_base_new中进行初始化:
for (i = 0; eventops[i] && !base->evbase; i++) { base->evsel = eventops[i]; base->evbase = base->evsel->init(base); }//
在
event_base_dispatch中调用
eventop结构体中的回调函数:
const struct eventop *evsel = base->evsel; res = evsel->dispatch(base, evbase, tv_p);
参考
深入浅出libevent相关文章推荐
- libevent高性能网络库源码分析——事件(event)及其接口(三)
- libevent源码学习-----event_base事件循环
- libevent源码深度剖析五 ——libevent的核心:事件event
- Libevent源码剖析——事件event
- nginx源码分析--event事件驱动初始化
- Cocos2d-X3.0 刨根问底(七)----- 事件机制Event源码分析
- libevent源码分析---基本使用场景和事件流程
- libevent源码分析--核心部分event
- jQuery源码分析-10事件处理-Event-DOM-ready
- 【转】Android笔记:触摸事件的分析与总结----Touch事件分发方法dispatchTouchEvent()源码分析
- libevent源码分析--evbuffer和bufferevent的关系
- nginx 源码学习笔记(二十一)—— event 模块(二) ——事件驱动核心ngx_process_events_and_timers
- jQuery源码分析-10事件处理-Event-源码结构
- Libevent源码分析-----event优先级设置
- Libevent源码分析-----信号event的处理
- Libevent源码分析-----event-config.h指明所在系统的环境
- libevent源码分析--事件处理框架
- nginx 源码学习笔记(二十一)—— event 模块(二) ——事件驱动核心ngx_process_events_and_timers
- libevent源码分析--event_set()函数
- Libevent源码分析-----event_signal_map