赞
踩
项目中要用到libevent,所以就自学了libevent,参考资料为张亮的《libevent源码深度剖析》和《linux高性能服务器编程》
Libevent简介
Libevent是开源社区一款高性能的I/O框架库,其具有如下特点:
1.跨平台支持。Libevent支持Linux、UNIX和Windows。
2.统一事件源。libevent对i/o事件、信号和定时事件提供统一的处理。
3.线程安全。libevent使用libevent_pthreads库来提供线程安全支持。
4.基于reactor模式的实现。
reactor基本知识
reactor是i/o框架库的核心,它主要提供的几个方法是:
1.handle_events:该方法执行事件循环,重复如下过程:等待事件,然后依次处理所有就绪事件对应的时间处理器。
2.register_handler:该方法调用事件多路分发器的register_event方法来往事件多路分发器中注册一个事件。
3.remove_handler:该方法调用事件多路分发器的remove_event方法来删除事件多路分发器中的一个事件。
下图为i/o框架库的工作时序图:
reactor具有如下优点:
1.响应快,不必为单个同步事件所阻塞;
2.编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;
3.可扩展性,可以方便的通过增加reactor实例个数来充分利用CPU资源;
4.可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性。
libevent库的主要逻辑:
1.调用event_init函数创建event_base对象。一个event_base相当于一个reactor实例。
2.创建具体的事件处理器,并设置它们所从属的reactor实例。evsignal_new和evtimer_new分别用于创建信号事件处理器和定时事件处理器,它们的统一入口是event_new函数,event_new函数成功时返回一个event类型的对象,也就是libevent的事件处理器
3.调用event_add函数,将事件处理器添加到注册事件队列中,并将该事件处理器对应的事件添加到事件多路分发器中。
4.调用event_base_dispatch函数来执行事件循环。
5.事件循环结束后,使用*_free系列函数来释放系统资源。
源代码组织结构
1)头文主要就是 event.h:事件宏定义、接口函数声明,主要结构体 event 的声明;
2)内部头文件
xxx-internal.h:内部数据结构和函数,对外不可见,以达到信息隐藏的目的;
3) libevent 框架
event.c: event 整体框架的代码实现;
4)对系统 I/O 多路复用机制的封装
epoll.c:对 epoll 的封装;
select.c:对 select 的封装;
devpoll.c:对 dev/poll 的封装;
kqueue.c:对 kqueue 的封装;
5)定时事件管理
min-heap.h:其实就是一个以时间作为 key 的小根堆结构;
6)信号管理
signal.c:对信号事件的处理;
7)辅助功能函数
evutil.h 和 evutil.c:一些辅助功能函数,包括创建 socket pair 和一些时间操作函数:加、减
和比较等。
8)日志
log.h 和 log.c: log 日志函数
9)缓冲区管理
evbuffer.c 和 buffer.c: libevent 对缓冲区的封装;
10)基本数据结构
compat\sys 下的两个源文件: queue.h 是 libevent 基本数据结构的实现,包括链表,双向链表,
队列等; _libevent_time.h:一些用于时间操作的结构体定义、函数和宏定义;
11)实用网络库
http 和 evdns:是基于 libevent 实现的 http 服务器和异步 dns 查询库;
event结构体
libevent中的事件处理器是event结构类型。event结构体封装了句柄、事件类型、回调函数、以及其他必要的标志和数据,源代码如下
- struct event {
- 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;
- short ev_res; /* result passed to event callback */
- short ev_flags;
- 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;
- };
ev_active_next: 表示就绪状态的事件链表指针,当关注的事件就绪后,会把往注册事件队列中添加事件处理器
创建一个event对象的函数是event_new,创建好之后应用程序调用event_add函数将其添加到注册事件队列中,并将对应的事件注册到事件多路分发器上,event_add函数主要是调用一个内部函数event_add_internal来实现的。
eventop结构体
eventop结构体封装了i/o复用机制必要的一些操作,比如注册事件、等待事件等,它为event_base支持的所有后端i/o复用机制提供了一个统一的接口,libevent默认选择的后端i/o复用技术是epoll。
event_base结构体
结构体event_base是libevent的reactor,源码如下:
- struct event_base {
- /** Function pointers and other data to describe this event_base's
- * backend. */
- const struct eventop *evsel;
- /** Pointer to backend-specific data. */
- void *evbase;
-
- /** List of changes to tell backend about at next dispatch. Only used
- * by the O(1) backends. */
- struct event_changelist changelist;
-
- /** Function pointers used to describe the backend that this event_base
- * uses for signals */
- const struct eventop *evsigsel;
- /** Data to implement the common signal handelr code. */
- struct evsig_info sig;
-
- /** Number of virtual events */
- int virtual_event_count;
- /** Number of total events added to this event_base */
- int event_count;
- /** Number of total events active in this event_base */
- int event_count_active;
-
- /** Set if we should terminate the loop once we're done processing
- * events. */
- int event_gotterm;
- /** Set if we should terminate the loop immediately */
- int event_break;
- /** Set if we should start a new instance of the loop immediately. */
- int event_continue;
-
- /** The currently running priority of events */
- int event_running_priority;
-
- /** Set if we're running the event_base_loop function, to prevent
- * reentrant invocation. */
- int running_loop;
-
- /* Active event management. */
- /** An array of nactivequeues queues for active events (ones that
- * have triggered, and whose callbacks need to be called). Low
- * priority numbers are more important, and stall higher ones.
- */
- struct event_list *activequeues;
- /** The length of the activequeues array */
- int nactivequeues;
-
- /* common timeout logic */
-
- /** An array of common_timeout_list* for all of the common timeout
- * values we know. */
- struct common_timeout_list **common_timeout_queues;
- /** The number of entries used in common_timeout_queues */
- int n_common_timeouts;
- /** The total size of common_timeout_queues. */
- int n_common_timeouts_allocated;
-
- /** List of defered_cb that are active. We run these after the active
- * events. */
- struct deferred_cb_queue defer_queue;
-
- /** Mapping from file descriptors to enabled (added) events */
- struct event_io_map io;
-
- /** Mapping from signal numbers to enabled (added) events. */
- struct event_signal_map sigmap;
-
- /** All events that have been enabled (added) in this event_base */
- struct event_list eventqueue;
-
- /** Stored timeval; used to detect when time is running backwards. */
- struct timeval event_tv;
-
- /** Priority queue of events with timeouts. */
- struct min_heap timeheap;
-
- /** Stored timeval: used to avoid calling gettimeofday/clock_gettime
- * too often. */
- struct timeval tv_cache;
-
- #if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
- /** Difference between internal time (maybe from clock_gettime) and
- * gettimeofday. */
- struct timeval tv_clock_diff;
- /** Second in which we last updated tv_clock_diff, in monotonic time. */
- time_t last_updated_clock_diff;
- #endif
-
- #ifndef _EVENT_DISABLE_THREAD_SUPPORT
- /* threading support */
- /** The thread currently running the event_loop for this base */
- unsigned long th_owner_id;
- /** A lock to prevent conflicting accesses to this event_base */
- void *th_base_lock;
- /** The event whose callback is executing right now */
- struct event *current_event;
- /** A condition that gets signalled when we're done processing an
- * event with waiters on it. */
- void *current_event_cond;
- /** Number of threads blocking on current_event_cond. */
- int current_event_waiters;
- #endif
-
- #ifdef WIN32
- /** IOCP support structure, if IOCP is enabled. */
- struct event_iocp_port *iocp;
- #endif
-
- /** Flags that this base was configured with */
- enum event_base_config_flag flags;
-
- /* Notify main thread to wake up break, etc. */
- /** True if the base already has a pending notify, and we don't need
- * to add any more. */
- int is_notify_pending;
- /** A socketpair used by some th_notify functions to wake up the main
- * thread. */
- evutil_socket_t th_notify_fd[2];
- /** An event used by some th_notify functions to wake up the main
- * thread. */
- struct event th_notify;
- /** A function used to wake up the main thread from another thread. */
- int (*th_notify_fn)(struct event_base *base);
- };
事件循环
libevent中实现事件循环的函数是event_base_loop,该函数首先调用i/o事件多路分发器的事件监听函数,以等待事件,当有事件发生时,就依次处理之。
参考博客:点击打开链接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。