标签:nts 恢复 封装 methods war 环境变量 initial res 基本操作
源码版本:2.1.11-stable
核心思想:Reactor模型(事件驱动)
处理的事件类型:网络IO读写,定时器,信号
它是一种“事件驱动”机制。程序想处理某个事件,需要提供相应的接口并注册到reactor上;如果相应的事件发生,reactor将主动调用此事件注册的接口,这些接口也称为“回调函数”。
使用libevent也是向libevent框架注册相应的事件和回调函数;当这些被注册的事件发生时,libevent会调用这些回调函数处理相应的事件。
reactor模型的组件:
事件源:
就是socket套接字,程序需要在套接字上注册所关心的事件,如IO事件
事件多路复用机制(event demultiplexer):
select 、poll、epoll等,;
程序首先将其注册了关心事件的回调的套接字注册到event demultiplexer上,
当有事件到达时,event demultiplexer会向已经注册的套接字集合发出通知 “一个或多个事件已经就绪”;
对应到libevent, 使用了结构体eventop对select、poll等进行了封装,以统一接口来实现IO多路复用机制;
reactor:
事件管理的接口,内部通过event demultiplexer进行事件的注册和注销操作;并运行事件循环,当有事件进入“就绪”状态时,就调用注册事件的回调函数来处理事件;
对应到libevent,就是结构体event_base;
事件处理程序:
事件处理程序提供一级接口,每个接口对应一种类型的事件,供reactor在相应事件发生时调用;
对应到libevent,就是结构体event;
#define EVENT_LOG_DEBUG 0 #define EVENT_LOG_MSG 1 #define EVENT_LOG_WARN 2 #define EVENT_LOG_ERR 3 typedef void (*event_log_cb)(int severity, const char *msg); void event_set_log_callback(event_log_cb cb);
手写日志回调,将其作为参数并调用event_set_log_callback(),将覆盖日志的默认行为;
日志默认输出到stderr, 再次调用event_set_log_callback()并传参NULL将恢复默认行为;
typedef void (*event_fatal_cb)(int err);
void event_set_fatal_callback(event_fatal_cb cb);
程序执行期间,遇到致使错误的默认行为是退出程序;
设置退出回调,可在程序异常退出前执行回调;
void event_set_mem_functions( void *(*malloc_fn)(size_t sz), void *(*realloc_fn)(void *ptr, size_t sz), void (*free_fn)(void *ptr));
替换默认的内存管理函数malloc, realloc, free
const char *event_get_version(void); ev_uint32_t event_get_version_number(void);
获取libevent版本信息
具体信息,参考《从一万英尺下看libevent》
struct event_base
struct event_base *event_base_new(void);
struct event_base *event_base_new_with_config(const struct event_config *);
struct event_config *event_config_new(void);
int event_config_avoid_method(struct event_config *cfg, const char *method);
int event_config_require_features(struct event_config *cfg, int feature);
enum event_method_feature { //flag
EV_FEATURE_ET = 0x01, //边沿触发
EV_FEATURE_O1 = 0x02, //添加、删除单个事件,或者确定哪个事件是激活状态的操作的时间复杂度是O(1)
EV_FEATURE_FDS = 0x04, //允许文件描术符和套接字
EV_FEATURE_EARLY_CLOSE = 0x08//在不需要检测所有未激活连接的情况,检测某个连接是否关闭
}
int event_config_set_flag(struct event_config *cfg, int flag);
enum event_base_config_flag {
EVENT_BASE_FLAG_NOLOCK = 0x01, //不分配锁
EVENT_BASE_FLAG_IGNORE_ENV = 0x02, //不检测EVENT_* 环境变量
EVENT_BASE_FLAG_STARTUP_IOCP = 0x04, //仅windows可用
EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08, //超时回调执行后检测当前时间
EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10,//使用epoll_changelist特征
EVENT_BASE_FLAG_PRECISE_TIMER = 0x20 //使用效率低但更精准的计时器
}
const char **event_get_supported_methods(void);
const char *event_base_get_method(const struct event_base *);
int event_base_get_features(const struct event_base *base);
void event_base_free(struct event_base *);
int event_base_priority_init(struct event_base *, int);
int event_reinit(struct event_base *base);
事件循环过程中,libevent是在等待并通知已经注册并发生的事件。
int event_base_loop(struct event_base *base, int flags)
flags:
#define EVLOOP_ONCE 0x01
#define EVLOOP_NONBLOCK 0x02
#define EVLOOP_NO_EXIT_ON_EMPTY 0x04
int event_base_dispatch(struct event_base *event_base)
int event_base_gettimeofday_cached(struct event_base *base, struct timeval *tv);
void event_base_dump_events(struct event_base *, FILE *);
事件是libevent的基本操作单元,每个事件代表一组条件的集合,条件包括:
调用libevent函数设置事件并关联到event_base之后,该事件进入“已初始化"状态(initiailzed);
此时,可以将其添加到event_base中,这使得其进入“未决”状态(pending);
在未决状态下,如果触发事件的条件发生(如超时,文件描述符状态改变),则事件进入“激活”状态(active),用户注册的事件回调函数将被执行;
如果事件配置为“持久的”(persistent),事件将保持为未决状态,否则事件不再未决;
删除操作可心让未决事件成为非未决(已初始化)的;
添加操作可以让非未决事件再次成为为未决的;
#define EV_TIMEOUT 0x01 //超时,在将事件添加到event_base时使用 #define EV_READ 0x02 //文件描述符可读 #define EV_WRITE 0x04 //文件描述符可写 #define EV_SIGNAL 0x08 //信号发生 #define EV_PERSIST 0x10 //未决状态持久 #define EV_ET 0x20 //边沿触发 #define EV_FINALIZE 0x40 //非阻塞调用event_del() #define EV_CLOSED 0x80 //连接关闭 typedef void (*event_callback_fn)(evutil_socket_t, short, void *); event_new(struct event_base *base, evutil_socket_t fd, short events, void (*cb)(evutil_socket_t, short, void *), void *arg);
默认情况下,事件从未决状态变成就绪状态后,事件将在执行事件回调前成为非未决状态;
如果想让事件再次成为未决状态,可以在回调函数内部再次将其添加到event_base;
然而,如果事件创建时设置了EV_PERSIST标志,则事件变成就绪态执行回调前不会变成非未决状态;
如果想让未决状态事件变成非未决状态,可调用event_del()执行删除操作;
#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg)) #define evtimer_add(ev, tv) event_add((ev), (tv)) #define evtimer_del(ev) event_del(ev) #define evtimer_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv)) #define evtimer_initialized(ev) event_initialized(ev)
使用这些宏函数,可以使设置纯超时事件更简便,当然,你也可以直接使用原生操作函数
#define evsignal_add(ev, tv) event_add((ev), (tv)) #define evsignal_del(ev) event_del(ev) #define evsignal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv)) #define evsignal_initialized(ev) event_initialized(ev)
int event_add(struct event *ev, const struct timeval *timeout);
int event_del(struct event *ev)
int event_priority_set(struct event *ev, int pri);
示例:
int event_pending(const struct event *ev, short event, struct timeval *tv);
功能:判断给定事件是否是未决或就绪状态
evutil_socket_t event_get_fd(const struct event *ev);
功能:返回事件的文件描述符
#define event_get_signal(ev) ((int)event_get_fd(ev))
功能:返回事件的信号值
struct event_base *event_get_base(const struct event *ev);
功能:返回事件的event_base
short event_get_events(const struct event *ev);
功能:返回事件的标志
event_callback_fn event_get_callback(const struct event *ev);
功能:返回事件的回调函数
void *event_get_callback_arg(const struct event *ev);
功能:返回事件回调函数的参数
void event_get_assignment(const struct event *event, struct event_base **base_out, evutil_socket_t *fd_out, short *events_out, event_callback_fn *callback_out, void **arg_out);
功能:返回上述所有
int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_fn, void *, const struct timeval *);
void event_active(struct event *ev, int res, short ncalls);
来自官方文档《从一万英尺外看libevent》
标签:nts 恢复 封装 methods war 环境变量 initial res 基本操作
原文地址:https://www.cnblogs.com/orejia/p/12127513.html