libevent学习(一)

1.libevent的特点

事件驱动,高性能;
轻量级,专注于网络;
跨平台,支持 Windows、Linux、Mac Os等;
支持多种 I/O多路复用技术, epoll、poll、dev/poll、select 和kqueue 等;
支持 I/O,定时器和信号等事件;

2.libevent安装与使用

官方网站: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

3.libevent事件处理流程

(1)创建一个事件处理框架

使用 libevent 函数之前需要分配一个或者多个 event_base 结构体。每个event_base 结构体持有一个事件集合,可以检测以确定哪个事件是激活的。相当于epoll红黑树的树根,每个 event_base 都有一种用于检测哪种事件已经就绪的 “方法”,或者说后端.

创建event_base:
struct event_base* event_base_new(void),失败返回NULL

(2)创建事件

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()函数之后, 新事件处于已初始化和非未决状态

(3)事件添加到事件处理框架上

构造事件之后,在将其添加到 event_base 之前实际上是不能对其做任何操作的。使用event_add()将事件添加到event_base, 非未决事件变成未决事件。非未决事件事件是指没有资格被处理,未决事件是有资格被处理但还没有处理,只有进入事件循环后才被处理。

int event_add(struct event *ev, const struct timeval *tv);

(4)开始事件循环

循环监听base对应的事件, 等待条件满足
event_base_dispatch();

(5)释放资源

释放event_base:
event_base_free(struct event_base* base);
释放事件
void event_free(struct event *event);

4.检查event_base的后端

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;
}

libevent学习(一)_第1张图片
5.libevent事件处理状态

libevent学习(一)_第2张图片

6.libevent使用读写FIFO

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;
}


 

 

你可能感兴趣的:(linux网络编程)