libevent源码深度剖析七
在本篇文章中,我们将继续深入分析libevent源码,重点探讨libevent中的事件机制。
事件机制
libevent中的事件机制使用了事件循环(event loop)和事件处理器(event handler),来帮助程序处理输入和输出(I/O),以及其他事件。当输入事件被触发,例如一个客户端连接到服务器,就会调用相应的事件处理器。事件处理器将会在一系列的回调函数中完成它的工作,例如读取请求数据、解析数据,并写回响应数据。
libevent中的事件机制主要由两个核心组件组成:
- event_base:事件循环基础设施,负责事件的调度与分发。
- evutil:提供了一些与事件处理相关的工具函数。
event_base
event_base是事件循环的基础设施,负责事件的调度和分发。所有的事件都要注册到event_base中,并通过它处理相关事件,举例来讲,如果一个socket对象处于“可读”状态,event_base会检测到这个状态,随后调用相关的回调函数进行处理并相应数据。
int event_base_dispatch(struct event_base* base);
int event_base_loop(struct event_base* base, int loop);
int event_base_loopbreak(struct event_base* base);
int event_base_loopexit(struct event_base* base, const struct timeval* tv);
event_base提供了4个主要的事件处理函数:
- event_base_dispatch:循环监听并处理事件,当没有事件时阻塞等待。
- event_base_loop:循环监听并处理事件,指定循环模式。loop模式有_EVLOOP_ONCE和_EVLOOP_NONBLOCK两种模式。
- event_base_loopbreak:终止事件循环,将会导致下一次event_base_loop函数返回。
- event_base_loopexit:事件循环终止,如果还有活动事件,则等到所有事件处理完毕后,才会退出。
evutil
evutil提供了一些事件处理相关的工具函数,这些函数主要用于管理和处理事件,其中最常用的是事件优先级和超时事件。下面列举一些经常用到的evutil函数:
- evutil_make_socket_nonblocking:设置套接字的非阻塞模式。
- evutil_make_listen_socket_reuseable:设置监听套接字可以在关闭后立即重用。
- evutil_make_socket_closeonexec:在fork或exec出子进程前关闭socket连接,防止它们被继承并耗用系统资源。
- evutil_socketpair:创建一对相互连接的socket。
- evutil_snprintf:安全的格式化字符串函数。
事件处理器
在libevent中,所有的事件处理器都注册在event_base上,一个事件处理器通常由下面几个函数组成:
- event_new:新建一个事件处理器。
- event_assign:设置用于处理事件的对象。
- event_add:将一个事件添加到事件处理器中。
- event_del:将一个事件从事件处理器中删除。
- event_priority_set:设置事件的优先级(默认按照添加时间排序,并且在处理相同类型的事件时不保证事件的处理顺序)。
- event_active:强制激活指定时间(一般不用)。
一个事件处理器通常由下面几个回调函数组成:
- event_callback_fn:所有的事件回调函数,必须包含该参数(必须回调函数参数一致,以下参数同)。
- event_thread_safe_callback_fn:线程安全的回调函数,可以跨线程访问。
- event_finalize_callback_fn:当事件处理器被释放时调用,用于清除资源。
总结
在本篇文章中,我们对libevent中的事件机制进行了深度剖析,事件机制关注I/O操作,利用事件循环和事件处理器实现高度效率的事件触发并完成相应操作。这些核心组件为我们的程序提供了强大的并发和异步I/O支持,同时我们也了解了事件处理器的建立和事件处理的基本流程,为我们在实际开发中使用libevent提供了参考借鉴。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:libevent源码深度剖析七 - Python技术站