简述
- Libevent适用于编写告诉可移植非阻塞IO应用的库
目的
- 可移植性
- 速度
- 可扩展性
- 方便
构成:
组件 | 说明 |
---|---|
evutil | 用于抽象不同平台网络实现差异的通用功能 |
event和event_base | 核心,为非阻塞IO后端提供抽象API,让程序知道套接字何时已准备好,可以读写,并且处理基本超时功能,检测OS信号 |
bufferevent | 为基于事件的核心提供使用更方便的封装 |
evbuffer | 在bufferevent层之下实现缓冲功能,并且提供访问函数 |
evhttp | 一个简单的HTTP客户端/服务器实现 |
evdns | 一个简单的DNS客户端/服务器实现 |
evrpc | 一个简单的RPC实现 |
库
库 | 说明 |
---|---|
ibevent_core | 核心时间和缓冲功能,包含event_base,evbuffer,bufferevent和工具函数 |
ibevent_extra | 定义协议特定功能,包括HTTP,DNS,RPC |
libevent_pthreads | 添加基于pthread可一直线程库的线程和锁定实现 |
libevent_openssl | 为使用bufferevent和OpenSSL进行加密的通信提供支持 |
说明
- libevent有一些被整个进程共享的影响整个库的全局设置,必须在调用libevent库的任何其他部分之前修改这些设置,否则libevent会进入不一致的状态
- 日志消息默认被写到stderr,通过提供定制的日志函数可以覆盖默认行为
- 编写event_log_cb函数,将其作为参数传递给event_set_log_callback(),再次调用该函数传递参数NULL就可以恢复默认为
typedef void (*event_log_cb)(int severity, const char* msg);
void event_set_log_callback(event_log_cb cb);
- 当检测到不可恢复的内部错误时,默认调用exit()或者abort(),如果希望自定义行为,可以为libevnet提供在退出时应该调用的函数,覆盖默认行为。
- 首先定义libevent在遇到错误时应该调用的函数,将其传递给event_set_fatal_callback(),
typedef void (*event_fatal_cb)(int err);
void event_set_fatal_callback(event_fatal_cb cb);
内存管理
- 默认情况下libevent 使用c库的内存管理函数分配内存,通过提供malloc,realloc和free的代替函数,可以让libevent使用其他的内存管理器
void event_set_mem_functions(void (*malloc_fa)(size_t sz),
void (*realloc_fa)(void* ptr, size_t sz),
void (*free_fas)(void* ptr));
//必须在调用其他函数之前进行替换
//自定义的函数应该地址对齐
//能正确realloc(NULL, sz);
//能正确realloc(ptr, 0)
//free函数不必处理free(NULL)
//malloc函数不必处理malloc(0)
//多线程下,函数应该是线程安全的
使用
创建event_base
说明
- 每个event_base结构体都持有一个事件集合,可以检测以确定哪个事件是激活的
- 如果设置了event_base使用锁,可以安全地在多个线程中访问,事件循环只能运行在一个吸纳成中,如果使用多线程检测IO,则需要为每个贤臣更实用一个event_base
- 每个event_base都有一个用于检测哪种事件已经就绪的方法,
- select
- poll
- epoll
- kqueue
- devpool
- evport
- win32
- 用户可以使用环境变量禁止某些特定的后端,可以设置EVENT_NOKQUEUR来禁止kqueue
建立
1. `event_base_new()`返回一个新的默认设置的的event_base的指针,如果发生错误返回NULL,
* `struct event_base *event_base_new(void);`
2. event_config是一个容纳event_base配置信息的不透明结构体,需要event_base时,将event_config传递给event_base_new_with_config()
3. 先调用event_config_new()分配一个event_config,然后对event_config调用其它函数,设置所需要的event_base特征,最后调用event_base_with_config()获取新的event_base(),使用event_config_free()释放event_config
4. 如果创建了libevent不能满足的配置,当event_base_new_with_config()会返回NULL
struct event_config* event_config_new(void);
struct event_base* event_base_new_with_config(const struct event_config* cfg);
void event_config_free(struct event_config* cfg);
event_config_avoid_method(); //通过名字让libevent避免使用特定的可用后端
event_config_require_feature()// 让libevent不使用不能提供所有指定特征的后端
//EV_FEATURE_ET:要求支持边沿触发的后端
//EV_FEATURE_O1:要求添加,删除单个事件,或者确定哪个事件激活的操作是O(1)复杂度的后端
//EV_FEATURE_FDS :要求支持任意文件描述符,而不仅仅是套接字的后端
event_config_set_flag() //让libevent在创建event_base时设置一个或者多个运行时标志
检查event_base后端的方法
const char** event_get_supported_methonds(void)
,指向libevent支持的方法名字数组,这个数组的最后一个元素是NULL
const char* event_base_get_method(const struct event_base* base);
返回event_base正在使用的方法,
enum event_method_feature event_base_get_features(const struct event_base* base);
返回event_base支持的特征的比特掩码
释放
void event_base_free(struct event_base *base);
设置event_base优先级
int event_base_priority_init(struct event_base* base, int n_priorities);
int event_base_get_npriorities(strcut event_base* base)
* 成功时返回0,失败返回-1,优先级设置至少为1
* 每个新的事件可用的优先级将从0(最高)到n_priorities-1(最低)
* 常量EVENT_MAX_PRIORITIES表示n_priorities的上限
* 必须在任何事件激活之前调用这个函数,最好在创建event_base后立刻调用
* 默认,与event_base相关事件将被初始化为具有优先级n_priorites/2
在fork()之后重新初始化event_base
int event_reinit(struct event_base* base)
* 成功时返回0,失败返回-1
与事件循环一起工作
运行循环
- 一但有一个已经注册了默写事件的event_base,就需要让libevent等待事件并且通知事件的发生
#define EVLOOP_ONCE 0x01 //等待事件成为激活,执行激活的事件知道没有更多的事件可以执行,然后返回
#define EVLOOP_NONBLOCK 0x02 //不会等待事件被触发,检测是否有事件就绪,可以立即出发,如果有则执行事件的回调
int event_base_loop(struct event_base* base, int flags);
int event_base_loopexit(struct event_base *base, const struct timeval *tv); //tv为NULL时会立即停止,如果event_base正在执行任何激活事件的回调,则会运行完所有的激活事件的回调才退出
int event_base_loopbreak(struct event_base *base); //执行完当前正在处理的事件后立即退出
//成功返回0,失败返回-1
event_base_dispatch() //等同于没有设置标志的event_base_loop(),所以会一直运行,知道没有已经注册的事件了,\
调用evetn_base_loopbreak()或者event_base_loopexit()为止
int event_base_got_exit(struct event_base *base);
int event_base_got_break(struct evetn_base* base);
//调用上述函数来确定是否调用了loopexit或者break函数
//是返回true,否则false
- 默认上述函数运行event_base知道其中没有已经注册的事件为止
- 正常退出返回0,否则-1
事件
- 每个事件代表一组条件的集合,(可读或可写; 文件描述符变为就绪,超时,发生某信号,用户触发事件)
- 设置事件–>