libevent简介
libevent是一个开源的高性能I/O框架,是基于Reactor模式实现的。什么是Reactior模式,简单地说,Reactor一般包括以下几个组件,句柄(Handle)
,事件多路分发器(EventDemultiplexer)
,事件处理器(EventHandler)
。
用一个简单的unix socket编程的例子来说明:
- 句柄就是文件描述符fd,可以对其进行一些读写的操作。
- 事件就是某个文件描述符,可读,可写,或者出现错误等事件。
- 事件多路分发器,就是I/O多路复用(select, poll, epoll),再加上一个分发的逻辑。
- 事件处理器可以理解成一个回调函数,这个回调函数决定了出现I/O的时候应该做什么,也就是具体的业务。把事件处理器注册到事件多路分发器中,这样就会形成某个事件和某个事件处理器的之间的一个映射。
libevent中事件分为三种:
- I/O事件
- 信号事件
- 定时器事件
libevent的核心是事件循环,根据发生的事件,调用对应的事件处理器。
libevent安装
libevent是跨平台的,本人使用的是linux,只介绍linux下安装的方法
- 使用包管理工具apt或者yum等来下载,下载的版本由软件仓库提供的版本决定
- 源码编译,github源码,按readme操作即可
头文件包含:libevent所使用的头文件均在event2目录下
#include <event2/event.h>
#include <event2/xxx.h>
编译时需要加上 -levent
参数链接libevent库
libevent API
详细请参数官方API文档,这里简单介绍几个常用Data Structures和API
数据结构 | 功能 |
---|---|
struct event |
事件处理器,可以代表IO事件,信号事件,或者定时器事件 |
struct event_base |
Reactor实例,也可以理解为事件多路分发器,每个struct event 都要加入到struct event_base 才能生效 |
函数 | 功能 |
---|---|
event_base_new() |
创建event_base |
event_base_free() |
销毁event_base,释放内存 |
event_new() |
创建一个事件,可以是IO、信号、定时器事件 |
event_free() |
销毁一个事件,释放内存 |
event_add() |
把一个event加入到event_base的事件循环中 |
event_del() |
把event从event_base的事件循环中移除 |
event_base_dispatch() or event_base_loop() |
进入事件循环,一直运行直到没有待定的事件 |
event_base_loopbreak() or event_base_loopexit() |
退出事件循环 |
typedef void(*event_callback_fn)(evutil_socket_t, short, void *) |
指明回调函数的类型,第一个参数是fd,第二个参数是event类型,第三个参数是在注册的时候填入 |
事件类型 | |
---|---|
EV_TIMEOUT | 定时器超时 |
EV_READ | fd可读 |
EV_WRITE | fd可写 |
EV_SIGNAL | 信号产生 |
EV_CLOSE | fd关闭 |
基于event的Demo
实现一个简单echo服务器,并且捕获SIGINT信号,设定一个1秒的定时器。同时处理IO、信号、定时器三种事件
简单起见,不考虑错误处理
1 |
|
基于bufferevent的Demo
bufferevent是对I/O事件的一种更高层的抽象。把一个bufferevent和一个句柄绑定起来,并且设置这个bufferevent的属性EV_READ|EV_WRITE,那么就可以得到一个可读写的bufferevent,并设置响应的回调函数,处理buffer时的业务,处理buffer可写时候的业务。bufferevent有个特点就是,用户不需要关系真正的读写的操作,buffervevent会在读写缓冲区可用的时候自动操作。用户只需要关心把输入缓冲区的数据取出并且经过业务处理,然后把数据放入输出缓冲区即可,底层的I/O会自动完成,实现真正的异步操作。
对于echo服务器,核心代码就一行evbuffer_add_buffer(ouput, input)
把输入缓冲区的数据直接迁移到输出缓冲区,libevent使用struct evbuffer
这种数据结构,还可以避免过多数据的拷贝。
1 |
|
参考
官方文档是英文,但是阅读难度不高,建议阅读