libevent 使用流程
使用流程
- 创建一个事件处理框架
- 创建一个事件
- 事件添加到处理框架
- 开始事件循环
- 释放资源
事件处理框架 - event_base
- 使用libevent函数之前需要分配一个或者多个event_base结构体. 每个event_base结构体有一个事件集合,可以检测以确定哪个事件是激活的.
- 相当于epoll红黑树的树根
- 底座
- 抽象层,完成对event_base的封装
- 每个event_base都有一种用于检测那种事件已经就绪的"方法",或者说后端
- 具体操作
- 创建event_base
struct event_base* event_base_new(void);
- 失败返回NULL
- 释放event_base
event_base_free(struct event_base* base);
- 循环监听base对应的事件, 等待条件满足
event_base_dispatch(struct event_base* base);
- 创建event_base
- 查看event_base封装的后端(当前系统中支持那些函数)
const char **event_get_supported_methods();
- 返回一个字符串数组中
const char * event_base_get_method(const struct event_base *base);
- 返回当前使用的IO转接
- event_base和fork
- 子进程创建成功后,父进程可以继续使用event_base
- 子进程中需要继续使用event_base需要重新进行初始化
int event_reinit(struct event_base * base)
事件 - event
- 创建新事件
#define EV_TIMEOUT 0x01 // 废弃
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10 // 持续触发
#define EV_ET 0x20 // 边沿模式
typedef void(*event_callback_fn)(evutil_sockt_t,short,void *);
struct event *event_new(
struct event_base *base,
evutil_socket_t fd, // 文件描述符-int
shord what,
event_callback_fn cb, // 事件处理动作
void *arg
);
- 释放事件
void event_free(struct event *event);
-
设置未决事件(有资格但是没有被处理的事件)
- 构造事件之后,在将其添加到 event_base 之前实际上是不能对其做任何操作的。使用event_add()将事件添加到event_base, 非未决事件 -> 未决事件.
- 函数
int event_add( struct event *ev, const struct timeval *tv );
- tv:
- NULL: 事件被触发, 对应的回调被调用
- tv = {0, 100}, 如果设置的时间,
- 在改时间段内检测的事件没被触发, 时间到达之后, 回调函数还是会被调用
- 函数调用成功返回0, 失败返回-1
- 设置非未决(还没有资格被处理的事件)
int event_del(struct event *ev);
- 对已经初始化的事件调用 event_del()将使其成为非未决和非激活的。如果事件不是未决的或者激活的,调用将没有效果。成功时函数返回 0,失败时返回-1。
事件循环
- 开始循环
- 一旦有了一个已经注册了某些事件的 event_base, 就需要让 libevent 等待事件并且通知事件的发生。
#define EVLOOP_ONCE 0x01 事件只会被触发一次 事件没有被触发, 阻塞等 #define EVLOOP_NONBLOCK 0x02 非阻塞 等方式去做事件检测 不关心事件是否被触发了 #define EVLOOP_NO_EXIT_ON_EMPTY 0x04 没有事件的时候, 也不退出轮询检测
- int event_base_loop(struct event_base *base, int flags);
- 正常退出返回0, 失败返回-1
-
event_base_dispatch(struct event_base* base)
- 等同于没有设置标志的 event_base_loop()
- 将一直运行,直到没有已经注册的事件了,或者调用 了event_base_loopbreak()或者 event_base_loopexit()为止。
- 停止循环
- 返回值:成功0,失败-1
struct timeval{ long tv_sec; long tv_usec; };
- 如果 event_base 当前正在执行激活事件的回调 ,它将在执行完当前正在处理的事件后立即退出
int event_base_loopexit( struct event_base *base, const struct timeval *tv );
- 让event_base 立即退出循环
int event_base_loopbreak(struct event_base *base);