一、Libevent的地基event_base
在使用libevent的函数之前,需要先申请一个或event_base结构,相当于盖房子时的地基,在event_base基础上会有一个事件集合,可以检测哪个事件是激活的(就绪),通常情况下可以通过event_base_new函数获得event_base结构,函数如下:
struct event_base *event_base_new(void);
申请到event_base结构体指针可以通过event_base_free进行释放,函数如下:
void event_base_free(struct event_base *);
如果fork出了子进程,想在子进程这继续使用event_base,那么子进程需要对event_base重新初始化,函数如下:
int event_reinit(struct event_base *base);
对于不同系统而言,event_base就是调用不同的多路IO接口去判断事件是否已经激活,对于linux系统而言,核心调用的就是epoll,同时支持poll和select。
二、等待事件产生(循环等待event_loop)
Libevent在地基打好之后,需要等待事件的产生,也就是等待想要等待的事件的激活,那么程序不能退出,对于epoll来说,我们需要自己控制循环,而在libevent中也给我们提供了api接口。函数如下:
int event_base_loop(struct event_base *, int flags);
flags的取值:
- #define EVLOOP_ONCE 0x01:只触发一次,如果事件没有被触发,阻塞等待。
- #define EVLOOP_NONBLOCK:非阻塞方式检测事件是否被 触发,不管事件是否被触发,都会立即返回。
而大多数我们都调用libevent给我们提供的另一个api,函数如下:
int event_base_dispatch(struct event_base *);
调用该函数,相当于没有设置标志位的event_base_loop,程序将会一直运行,直到没有需要检测的事件了,或者被结束循环的api终止了。
int event_base_loopexit(struct event_base *, const struct timeval *); int event_base_loopbreak(struct event_base *);
两个函数的区别是如果正在执行激活事件的回调函数,那么event_base_loopexit将在事件回调执行结束后终止循环(如果tv时间非NULL,那么将等待tv设置的时间后立即结束循环),而event_base_loopbreak会立即终止循环。
三、事件驱动event
事件驱动实际上是libevent的核心思想,主要的状态转化如下:
主要的几个状态:
- 无效的指针:此时仅仅是定义了struct event *ptr;
- 非未决:相当于创建了事件,但是事件还没有处于被监听状态,类似于我们使用epoll的时候定义了struct epoll_event ev并且对ev的两个字段进行了赋值,但是此时尚未调用epoll_ctl。
- 未决:就是对事件开始监听,暂时未有事件产生,相当于调用epoll_ctl。
- 激活:代表监听的事件已经产生,这时需要处理,相当于epoll所说的事件就绪
Libevent的事件驱动对应的结构体为struct event,对应的函数在图上也比较清晰。
1.event_new函数
struct event *event_new(struct event_base *base, evutil_socket_t fd, short events, event_callback_fn cb, void *arg);
event_new负责新创建event结构体指针,同时指定对应的地基base,还用对应的文件描述符、事件、以及回调函数和回调函数的参数。参数说明:
- base:对应的根节点
- fd:要监听的文件描述符
- events:要监听的事件
- #define EV_TIMEOUT 0x01 //超时事件
- #define EV_READ 0x02 //读事件
- #define EV_WRITE 0x04 //写事件
- #define EV_SIGNAL 0x80 //信号事件
- #define EV_PERSIST 0x10 //周期性触发
- #define EV_ET 0x20 //边缘触发,如果底层模型支持
cb回调函数,原型如下:
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
arg回调函数的参数
2.event_add函数
int event_add(struct event *ev, const struct timeval *timeout);
将非未决态事件转为未决态,相当于调用epoll_ctl函数,开始监听事件是否产生。
参数说明:
- ev:就是前面event_new创建的事件
- timeout:限时等待事件的产生,也可以设置未NULL,没有限时。
3.event_del函数
int event_del(struct event *);
将事件从未决状态变为非未决状态,相当于epoll的下树(epoll_ctl调用EPOLL_CTL_DEL操作)操作。
4.event_free()函数
void event_free(struct event *);
释放event_ne申请的event节点
标签:struct,epoll,Libevent,入门级,base,事件,使用,event,函数 From: https://www.cnblogs.com/TechNomad/p/17875260.html