事件驱动,高性能;
轻量级,专注于网络;
跨平台,支持 Windows、Linux、Mac Os等;
支持多种 I/O多路复用技术, epoll、poll、dev/poll、select 和kqueue 等;
支持 I/O,定时器和信号等事件;
官方网站:http://libevent.org/ 下载安装包
tar -zxvf libevent-2.0.22-stable.tar.gz
cd libevent-2.0.22-stable/
./configure
make
sudo make install
编译程序的时候指定-levent即可,常用的头文件:
#include
#include
使用 libevent 函数之前需要分配一个或者多个 event_base 结构体。每个event_base 结构体持有一个事件集合,可以检测以确定哪个事件是激活的。相当于epoll红黑树的树根,每个 event_base 都有一种用于检测哪种事件已经就绪的 “方法”,或者说后端.
创建event_base:
struct event_base* event_base_new(void),失败返回NULL
struct event *event_new(
struct event_base *base,
evutil_socket_t fd, // 文件描述符 - int
short what,
event_callback_fn cb, // 回调函数,事件的处理动作
void *arg
);
回调函数cb:
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
事件处理方式what参数:
#define EV_TIMEOUT 0x01 // 废弃
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10 // 持续触发
#define EV_ET 0x20 // 边沿模式
调用event_new()函数之后, 新事件处于已初始化和非未决状态
构造事件之后,在将其添加到 event_base 之前实际上是不能对其做任何操作的。使用event_add()将事件添加到event_base, 非未决事件变成未决事件。非未决事件事件是指没有资格被处理,未决事件是有资格被处理但还没有处理,只有进入事件循环后才被处理。
int event_add(struct event *ev, const struct timeval *tv);
循环监听base对应的事件, 等待条件满足
event_base_dispatch();
释放event_base:
event_base_free(struct event_base* base);
释放事件
void event_free(struct event *event);
const char **event_get_supported_methods(void);
event_get_supported_methods()函数返回一个指针 ,指向 libevent 支持的方法名字数组,这个数组的最后一个元素是 NULL
每个 event_base 都有一种用于检测哪种事件已经就绪的 “方法”,或者说后端。可以识别的方法有:
select,poll,epoll,kqueue等
const char *event_base_get_method(const struct event_base *base);
enum event_method_feature
event_base_get_features(const struct event_base *base);
vent_base_get_method()返回 event_base 正在使用的方法
event_base_get_features ()返回 event_base 支持的特征的比特掩码
#include
#include
#include
int main()
{
int i;
const char **methods = event_get_supported_methods();
printf("Starting Libevent %s. Available methods are:\n",event_get_version());
for (i=0; methods[i] != NULL; ++i) {
printf(" %s\n", methods[i]);
}
struct event_base *base;
enum event_method_feature f;
base = event_base_new();
if (!base) {
puts("Couldn't get an event_base!");
}
else {
printf("Using Libevent with backend method %s.",event_base_get_method(base));
f = event_base_get_features(base);
if ((f & EV_FEATURE_ET))
printf(" Edge-triggered events are supported.\n");
if ((f & EV_FEATURE_O1))
printf(" O(1) event notification is supported.\n");
if ((f & EV_FEATURE_FDS))
printf(" All FD types are supported.\n");
}
return 0;
}
read_fifo.c
#include
#include
#include
#include
#include
#include
#include
#include
// 对操作处理函数
void read_cb(evutil_socket_t fd, short what, void *arg)
{
// 读管道
char buf[1024] = {0};
int len = read(fd, buf, sizeof(buf));
printf("data len = %d, buf = %s\n", len, buf);
printf("read event: %s", what & EV_READ ? "Yes" : "No");
}
// 读管道
int main(int argc, const char* argv[])
{
unlink("myfifo");
//创建有名管道
mkfifo("myfifo", 0664);
// open file
int fd = open("myfifo", O_RDONLY | O_NONBLOCK);
if(fd == -1)
{
perror("open error");
exit(1);
}
// 创建框架event_base
struct event_base* base = NULL;
base = event_base_new();
// 创建事件
struct event* ev = NULL;
ev = event_new(base, fd, EV_READ | EV_PERSIST, read_cb, NULL);
// 添加事件
event_add(ev, NULL);
// 事件循环
event_base_dispatch(base);
// 释放资源
event_free(ev);
event_base_free(base);
close(fd);
return 0;
}
write_fifo.c
#include
#include
#include
#include
#include
#include
#include
#include
// 对操作处理函数
void write_cb(evutil_socket_t fd, short what, void *arg)
{
// write管道
char buf[1024] = {0};
static int num = 0;
sprintf(buf, "hello, world == %d\n", num++);
write(fd, buf, strlen(buf)+1);
sleep(5);
}
// 写管道
int main(int argc, const char* argv[])
{
// open file
int fd = open("myfifo", O_WRONLY | O_NONBLOCK);
if(fd == -1)
{
perror("open error");
exit(1);
}
// 创建框架event_base
struct event_base* base = NULL;
base = event_base_new();
// 创建事件
struct event* ev = NULL;
// 检测的写缓冲区是否有空间写
ev = event_new(base, fd, EV_WRITE | EV_PERSIST, write_cb, NULL);
// 添加事件
event_add(ev, NULL);
// 事件循环
event_base_dispatch(base);
// 释放资源
event_free(ev);
event_base_free(base);
close(fd);
return 0;
}