libevent网络库

Libevent

是一个用C语言编写的、轻量级的开源高性能事件通知库。作为底层的网络库,比如 memcached、 Vomit、 Nylon、 Netchat等等。编译库的代码时,编译的脚本将会根据OS支持的处理事件机制,来编译相应的代码,从而在libevent接口上保持一致。

主要有以下:
事件驱动( event-driven),高性能;
轻量级,专注于网络,不如 ACE 那么臃肿庞大;
源代码相当精炼、易读;
跨平台,支持 Windows、 Linux、 *BSD 和 Mac Os;
支持多种 I/O 多路复用技术, epoll、 poll、 dev/poll、 select 和 kqueue 等;
支持 I/O,定时器和信号等事件;
注册事件优先级;

适用于:windows,linux,bsd等多种平台,内部使用select,epoll,kqueue,IOCP等系统调用管理事件机制。

libevent支持用户使用三种类型的事件:

网络IO,定时器,信号。
定时器的实现使用:最小堆的数据结构,以达到高效查找,排序,删除定时器的目的。
IO和信号的实现使用:双向队列(链表实现)epoll

提供DNS,HTTP Server,RPC等组件。
支持多线程编程,每个事件需要关联到自己的event_base。

主要组成:

事件管理,缓存管理,DNS,HTTP,缓存事件。
事件管理包括各种IO(socket)、定时器、信号等事件;
缓存管理是指evbuffer功能;
DNS是libevent提供的一个异步DNS查询功能;
HTTP是libevent的一个轻量级http实现,包括服务器和客户端。

I/O复用:

   代码例子:
//事件回调处理函数
Static void MyCallBack(const int fd, constshort which, void *arg)
{
       If(EV_READ==which){
              //读事件处理
}
……
}
Int main(int argc, char** argv)
{
       //初始化libevent
       structevent_base *pEventBase;
       pEventBase =event_init();

       intsock=socket(……);

       struct event event;
       event_set(&event , sock, EV_READ | EV_PERSIST,MyCallBack, (void*)0 );
       event_base_set(pEventBase, &event);

       event_add(&event, 0);
       event_base_loop(pEventBase, 0);
       Return0;
}

event_int: 初始化libevent库
event_set:赋值structevent结构,用event_add把该事件结构增加到事件循环,用event_del从事件循环中删除。支持的事件类型可以是下面组合:EV_READ(可读), EV_WRITE(可写),EV_PERSIST(除非调用event_del,否则事件一直在事件循环中)
event_base_set:修改struct_event事件结构所属的event_base为指定的event_base。Libevnet内置一个全局的event_base结构。多个线程应用中,如果多个线程都需要一个libevent事件循环,需要调用event_base_set修改事件结构基于的event_base。
event_add:增加事件到事件监控中。
event_base_loop:事件循环。调用底层的select、poll或epoll等,如监听事件发生,调用事件结构中指定的回调函数。

event处理流程:

1、设置event_base(即初始化Reactor)
2、设置event事件(初始化event)
3、将event和event_base关联(将event注册到event_base)
4、进入循环,等待事件
5、事件发生,处理事件。

定时器:

     代码例子:
struct event g_clockevent;
struct event_base *g_pEventBase;
#define evtimer_set(ev, cb, arg)
void clock_handler(const int fd, constshort which, void *arg)
{     

       static bool initialized = false;
       if(initialized) {
              evtimer_del(&g_clockevent);
       }
       else {
              initialized= true;
       }

       evtimer_set(&g_clockevent, clock_handler, (void*) 0);//设置定时器事件

       //定时器时间
       struct timeval t ;
       t.tv_sec=1;
       t.tv_usec=0;

       event_base_set(g_pEventBase, &me->m_clockevent);//将event和event_base关联
       if(evtimer_add(&clock_handler, &t) == -1){            
              return;
       }//注册事件

       //自定义事件处理
       .....
}
int main(int argv, char** argc)
{
       g_pEventBase=event_init();
       clock_handler(0,0,(void*)0);
       return0;
}

evtimer_set: 设置定时器事件。
evtimer_add: 增加定时器时间。

重要结构体:

struct eventop:对select/pool/epoll/kqueue等底层函数,按照该结构提供的接口方式,封装接口统一的函数。

struct eventop {
constchar *name;
void*(init)(struct event_base );
int(add)(void , struct event *);
int(del)(void, struct event *);
int(dispatch)(struct event_base , void , struct timeval );
void(dealloc)(struct event_base , void *);
/set if we need to reinitialize the event base /
intneed_reinit;
};
struct event_base:相当于一个事件池。一个线程一个。使用提供的API,把需要监控的事件结构加入到该事件池中。

struct event_base {
conststruct eventop *evsel; //指向编译时选择的一个select/pool/epoll/kqueue接口封装对象。
void*evbase;
intevent_count; /* counts numberof total events */
intevent_count_active; /* counts number ofactive events */
intevent_gotterm; /* Set to terminateloop */
intevent_break; /* Set toterminate loop immediately */
/active event management /
structevent_list **activequeues; //活动事件队列
intnactivequeues;
/signal handling info /
structevsignal_info sig;
structevent_list eventqueue; //监听事件队列
structtimeval event_tv;
structmin_heap timeheap; //定时器时间堆
structtimeval tv_cache;
};

struct event:事件结构。

struct event {
TAILQ_ENTRY(event) ev_next;
TAILQ_ENTRY(event) ev_active_next;
TAILQ_ENTRY(event) ev_signal_next;
unsignedint min_heap_idx; /* for managingtimeouts */
struct event_base *ev_base; //事件输入的evnet_base
intev_fd;
short ev_events;
short ev_ncalls;
short*ev_pncalls; /* Allows deletes incallback */
struct timeval ev_timeout;
intev_pri; /* smaller numbers arehigher priority */
void(*ev_callback)(int, short, void *arg); //回调函数
void*ev_arg;
intev_res; /* result passed toevent callback */
intev_flags;
};

主要函数介绍:

(1)event_init函数
调用event_base_new,初始化struct event_base对象。
event_base_new里做了如下工作:
1、 申请内存
2、 初始化定时器堆和事件队列
3、 为event_base对象选择底层事件函数封装对象。根据编译选项,初始化eventops全局对象。该对象存放指向底层select/pool/epoll等功能的封装函数。
4、 初始化活动队列。

(2)event_set函数
初始化struct event对象。
event_set(struct event *ev, int fd, short events) //ev,事件指针,fd,事件需要绑定的文件描述符,events,时间类型,可以是EV_TIMEOUT,EV_READ等,
1. 绑定ev到event_base
2. 设定ev的回调函数与参数
3.设定ev绑定的文件描述符
4.设定时间类型(EV_TIEMOUT,EV_READ,EV_WRITE等)
5.初始化ev在最小堆中的默认序号为-1
6.设定ev的优先级

(3)event_base_set函数
把struct event对象指向的event_base对象赋值为指定的对象。
event_base_set()函数是作为event_set()的补充,该函数重新设置ev绑定的eventbase与ev的优先级
如果是通过event_base_new()创建的base,需要先调用event_set()函数先初始化event,再调用event_base_new()重新设置ev绑定的新的base

(4)event_base_add函数
增加指定event到监控池里。
1、 对于读、写、信号事件,调用封装的add函数,调用底层select/pool/epoll相关函数,增加到操作系统事件监控里。对于epoll,调用的是epoll_add函数。Epoll_add函数调用epoll_ctl添加事件监控,libevent使用水平触发方式。把监听时间加入到event_base的事件队列中。
2、 对应定时器事件,加入到event_base的定时器最小堆里。
3、 对信号事件,调用evsignal_add,加入事件处理队列中。

(5)event_base_loop函数
事件循环,事件发生后,调用相应回调函数。
1、 计算最近的超时时间:定时器最小堆按照超时时间排序,取最小的超时时间;如已有活动事件或指定不阻塞,超时时间为0。
2、 调用dispatch。对epoll,对应epoll_dispatch函数。该函数调用epoll_wait监控指定事件。
3、 把到了超时时间的事件加入到活动事件队列。从超时时间最小堆中依次取最小超时时间和当前时间比较,对小于/等于当前时间的事件,加入到活动事件队列。
4、 循环调用活动事件队列中所有事件的回调函数。

(6)epoll_dispatch函数
1. 计算epoll_wait函数需要的超时时间,把时间转换成微妙。
2. 如epoll_wait被信号中断,把相应信号对应的事件加入到活动事件队列。
3. 如监视的描述上发生了特定事件,把相应事件对象加入到活动事件队列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值