Libevent是一个用C语言编写的基于事件触发的开源高性能网络库。著名的分布式缓存软件memecached也是基于libevent,适用于windows,linux,ios等多种平台。大量用到回调函数(函数指针)的方法。于此类似的有ACE,ASIO。
优点:
1.libevent是一个事件触发的网络库。专注与网络
2.跨平台。
3.使用select,dev/poll(Solaris),epoll(linux),kqueue(freebsd),IOCP(windows)等系统调用管理事件机制(IO多路复用技术)。
4.支持I/O,定时器,信号等事件。(统一事件源)
Libevent的组件和库
1.evtil:用于抽象不同的平台的网络实现。
2.event,event_base为libevent的核心,为不同的平台下基于事件的非阻塞IO提供了接口。
3.bufferevent对libevent的基于事件的核心的封装。应用程序的读写请求是基于缓冲区的。
4.Evbuffer为bufferevent实现的缓冲区。
5.Evhttp:一个简单的http client/server 的实现。
6.Evdns:一个简单的dns client/server的实现。
7.Evrpc:一个简单的rpc实现。
Libevent的功能
Libevent提供了事件通知,io缓存事件,定时器,超时,异步解析dns,事件驱动的http server以及一个rpc框架。
事件通知:当文件描述符可读可写时将执行回调函数。
IO缓存:缓存事件提供了输入输出缓存,能自动的读入和写入,用户不必直接操作IO。
定时器:libevent提供定时器的机制,能够在一定时间间隔之后执行回调函数。
信号:触发信号,执行回调。
异步解析dns:一部解析dns服务器的dns解析函数集。
Rpc客户端服务器框架:能自动的封装和解封装数据结构。
Reactor反应堆模式
整个libevent就是一个Reactor。
Reactor是一种事件处理的机制。
普通函数的调用机制:
程序调用函数—》函数执行,程序等待—》函数将结果和控制权返回 程序—》程序继续执行。(在函数没有返回的过程中,程序一直阻塞)。
Reactor模式的做法:
逆置了普通函数的事件处理流程,应用程序需要提供相应的接口并注册到reactor上,如何相应的时间发生,reactor会主动调用应用程序注册的接口,处理事件,这些接口就是“回调函数”。
Reactor的框架
组件:事件源,reactor框架,多路复用机制,事件处理。
1》事件源—Handle(句柄集)
管理文件描述符或者信号值的机制,即统一了三类事件:IO,信号量,定时器
2》事件多路分发机制—–event demultiplexer
OS提供的IO多路复用机制,程序首先将其关心的句柄及其事件注册在event demultiplexer上,事件到达,event demultiplexer就会发出通知“一个或多个事件就绪”,程序收到通知后,就会对事件进行处理。对应于结构体eventop。
3》反应器—Reactor
事件管理的接口,内部使用event demultiplexer注册注销事件,并运行事件循环,当有事件进入“就绪”状态,调用注册事件的回调函数处理事件。对应于结构体event_base。
4》事件处理程序–Event Hander
事件源只是来对多个fd进行管理,而真正对三类事件的封装则是在Event Hander里面,它有一组接口,每个接口对应一种事件类型,供Reactor在相应的事件发生时调用,执行相应的事件处理。对应结构体event。
#define TAILQ_ENTRY(type)
struct {
struct type *tqe_next;
struct type **tqe_prev;
};
//TAILQ_HEAD(event_list,event)
#define TAILQ_HEAD(name,type)
struct name{
struct type *tqh_first;
struct type **tqh_last;
};
struct event{
TAILQ_ENTRY(event) ev_active_next;
TAILQ_ENTRY(event) ev_next;
struct event_base *ev_base;
int ev_fd; //evutil_socket_t
union{
TAILQ_ENTRY(event) ev_next_with_common_timeout;
int min_heap_idx;
}ev_timeout_pos;
union{
struct {
TAILQ_ENTRY(event) ev_io_next;
struct timeval ev_timeout;
}ev_io;
struct{
TAILQ_ENTRY(event) ev_signal_next;
short ev_ncalls;
short *ev_pncalls;
}v_signal;
}_ev;
short ev_events;//event类型
short ev_res; //
short ev_flags; //event状态
unsigned char ev_pri; //ev_uint8_t
//ev_closure的作用就是告诉在事件处理时调用不同的处理函数。
unsigned char ev_closure; //回调函数的类型
struct timeval ev_timeout;
void(*ev_callback)(int, short, void *arg);
void *ev_arg;
};
//ev_events; //event类型
#define EV_TIMEOUT 0x01
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGAL 0x08
#define EV_PERSIST 0x10 //永久事件
#define EV_ET 0x20 //ET边缘触发
//ev_flags; //event状态
#define EVLIST_TIMEOUT 0x01 //事件在堆中
#define EVLIST_INSERTED 0x02 //事件已经注册到链表中
#define EVLIST_SIGNAL 0x04 //
#define EVLIST_ACTIVE 0x08 //事件激活链表中
#define EVLIST_INTERNAL 0x10 //
#define EVLIST_INIT 0x80 //事件已经初始化
//ev_closure; //回调函数的类型
#define EV_CLOSURE_NONE 0 //其他
#define EV_CLOSURE_SIGNAL 1 //signal
#define EV_CLOSURE_PERSIST 2 //永久
struct eventop{
const char *name;//IO多路复用机制
void *(*init)(struct event_base *);
void (*add)(struct base_base *, int fd, short old, short events, void *fdinfo);
void (*del)(struct base_base *, int fd, short old, short events, void *fdinfo);
void (*dispath)(struct event_base*, struct timeval *);
void (*dealloc)(struct event_base *);
int need_reinit;//是否需要重新初始化
enum event_method_feature feature; //
size_t fdinfo_len;
};
enum event_method_feature{
EV_FEATURE_ET = 0x01, //kqueue
EV_FEATURE_01 = 0x02, //kqueue,epoll,devpoll
EV_FEATURE_FDS= 0x04 //kqueue,epoll,devpoll,select,poll,
};
//evport,win32 对上设置为0
/*
* 当我们创建一个event_base时,libevent会帮我们选择最快的IO复用方式
* event_base_get_method(base);查看libevent具体选择了哪个IO复用方式
*/
struct event_base{
void *evbase;
const struct eventop *evsel;
const struct eventop *evsigsel;
struct evsig_info sig;
int event_count;
int event_count_active;
struct event_list *activequeues;
int nactivequeues;
struct event_io_map io;
struct event_signal_map sigmap;
struct event_list eventqueue;
struct timeval event_tv;
struct min_heap timeheap;
struct timeval tv_cache;
};