libevent事件的基本操作单位是事件,每个事件代表一组条件的集合,包括:
文件描述符就绪
文件描述符变为就绪(ET模式)
超时事件
发生某信号
用户触发事件
initialized:事件初始化,包括描述符,回调,关心的事件等
pending:事件已被添加到event_base中
active:事件发生,具体可表现为描述符可读或者可写,执行用户回调
persistent:执行用户回调后将回到pending状态,否则事件从event_base中移除
先看看在源码中对事件状态的和事件类型的宏定义
//event.h
#define EV_TIMEOUT 0x01
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10 /* Persistant event */
代码中使用event_new
来创建一个新事件:
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);//回调函数
//
struct event *event_new(struct event_base *,//event_base
evutil_socket_t, //fd
short,//flag: 可以包含EV_READ等
event_callback_fn, // call_back
void *);//args
一个简单的事例,用event监听可读事件(描述符为1),读入键盘输入并输出:
#include
#include
#include
#include
#include
#include
void read_cb(evutil_socket_t fd,short event,void *arg)
{
char buff[1024];
memset(buff,0x00,1024);
ssize_t n=read(fd,buff,1024);//read
buff[n]='\0';
printf("-----%s\r\n",buff);
}
int main(int argc,char **argv)
{
struct event_base* base=event_base_new();
assert(base!=NULL);
struct event* ev=event_new(base,//event_base
(evutil_socket_t)1,//fd
EV_READ|EV_PERSIST,//flags
read_cb,//callback
NULL);//args
event_add(ev,NULL);//add event
event_base_dispatch(base);//event loop
return 0;
}
在Libevent源码中提供了宏定义,方便处理信号事件,实际上是对event_new的包裹,比如:
#define evsignal_new(base,signum,cb,arg) \
event_new(base,signum,EV_SIGNAL|EV_PERSIST,cb,arg)
主要用信号编号代替文件描述符号
下面看一个例子:
#include
#include
#include
#include
#include
#include
#include
#include
void sig_cb(evutil_socket_t fd,short event,void *arg)
{
printf("In signal event callback\r\n");
struct event_base * base = (struct event_base *)arg;
event_base_loopbreak(base);//
}
int main(int argc,char **argv)
{
struct event_base* base=event_base_new();
assert(base!=NULL);
struct event* ev=evsignal_new(base,
(evutil_socket_t)SIGALRM,
sig_cb,
base);
evsignal_add(ev,NULL);//#define evsignal_add event_add
alarm(5);
event_base_dispatch(base);
printf("exit...\r\n");
return 0;
}
libevent深入浅出