Chinaunix首页 | 论坛 | 博客
  • 博客访问: 391174
  • 博文数量: 87
  • 博客积分: 2571
  • 博客等级: 少校
  • 技术积分: 920
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-29 13:10
文章分类

全部博文(87)

文章存档

2012年(49)

2011年(7)

2010年(26)

2009年(5)

分类: LINUX

2010-04-09 10:41:52

   libevent是一个事件触发的网络库,适用于windows、linux、bsd等多种平台,内部使用select、epoll、kqueue等系统调用管理事件机制。著名的用于apache的php缓存库memcached据说也是libevent based,而且libevent在使用上可以做到跨平台,而且根据libevent官方网站上公布的数据统计,似乎也有着非凡的性能。
    编译库代码,编译脚本会判断OS支持哪种类型的事件机制(select、epoll或kqueue),然后条件编译相应代码,供上层使用的接口仍然是保持统一的。
    libevent支持用户使用三种类型的事件,分别是网络IO、定时器、信号三种,在定时器的实现上使用了RB tree的数据结构,以达到高效查找、排序、删除定时器的目的,网络IO上,主要关注了一下linux上的epoll(因为目前的开发主要在linux平台),结果发现libevent的epoll居然用的EPOLLLT,水平触发的方式用起来比较方便,不容易出错,但是在效率上可能比EPOLLET要低一些。
    Libevent定时器的数据结构自version 1.4起已由红黑树改为最小堆(Min Heap),以提高效率;网络IO和信号的数据结构采用了双向链表(TAILQ)。在实现上主要有3种链表: EVLIST_INSERTED, EVLIST_ACTIVE, EVLIST_TIMEOUT,一个ev在这3种链表之间被插入或删除,处于EVLIST_ACTIVE链表中的ev最后将会被调度执行。
  Libevent提供了DNS,HTTP Server,RPC等组件,HTTP Server可以说是Libevent的经典应用。从http.c可看到Libevent的很多标准写法。写非阻塞式的HTTP Server很容易将socket处理与HTTP协议处理纠缠在一起,Libevent在这点上似乎也有值得推敲的地方。
 
   eventop结构体是所有事件驱动模型的基类。所有的io复用类型都会实现此结构体里各种方法
 

struct eventop {
    const char *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 */
    int need_reinit; ///<标志位
};

 

  event_base管理所有的event对象,它包含了一些全部变量,比如事件驱动引擎evsel等。所有的event对象都会包含这个结构体。


 

struct event_base {
    const struct eventop *evsel; ///<事件驱动引擎
    void *evbase; ///<事件驱动引擎的全局数据,在每一个事件引擎文件中定义,下面会介绍.
    int event_count;        /* counts number of total events */
    int event_count_active;    /* counts number of active events */
    int event_gotterm;        /* Set to terminate loop */
    int event_break;        /* Set to terminate loop immediately */
    /* active event management */
    struct event_list **activequeues; ///<激活队列
    int nactivequeues; ///<激活队列数目
    /* signal handling info */
    struct evsignal_info sig; ///<信号
    struct event_list eventqueue; ///<全部事件队列
    struct timeval event_tv; 
    struct min_heap timeheap; ///<这里libevent将定时器队列实现为一个最小堆,也就是为了每次都把时间最晚的定时器能取出来,然后实现超时。
    struct timeval tv_cache;
};


 

    event结构表示每个事件,包含了一些事件私有的数据,比如回调函数等。。这里事件链表它使用了tail queue

    

struct event {
    TAILQ_ENTRY (event) ev_next; ///<下一个事件
    TAILQ_ENTRY (event) ev_active_next; ///<下一个激活事件
    TAILQ_ENTRY (event) ev_signal_next; ///<下一个信号事件列表
    unsigned int min_heap_idx;    /* for managing timeouts */
    struct event_base *ev_base; ///<全局的base
    int ev_fd; ///<所需要监测的事件句柄
    short ev_events;
    short ev_ncalls;
    short *ev_pncalls;    /* Allows deletes in callback */
    struct timeval ev_timeout; ///<超时时间
    int ev_pri;        /* smaller numbers are higher priority */
    void (*ev_callback)(int, short, void *arg); ///<回调函数
    void *ev_arg; ///<传递给回调函数的参数
    int ev_res;        /* result passed to event callback */
    int ev_flags;
};

 

    事件引擎中的两个结构,这里主要介绍下select,其他的类似.
    selectop是全局的select数据结构,也就是上面event_base数据结构中evbase的值,通过avbase就可以操作select的数据结构

struct selectop {
    int event_fds;        /* Highest fd in fd set */
    int event_fdsz;
    fd_set *event_readset_in;
    fd_set *event_writeset_in;
    fd_set *event_readset_out;
    fd_set *event_writeset_out;
    struct event **event_r_by_fd;
    struct event **event_w_by_fd;
};

selectops也就是实现了eventop。它导出了select的接口。
const struct eventop selectops = {
    "select",
    select_init,
    select_add,
    select_del,
    select_dispatch,
    select_dealloc,
    0
};

 

libevent中几个核心函数:

    event_set(&c->event, sfd, event_flags, event_handler, (void *)c)
把sfd这个文件描述符放入c->event,并且告知当事件event_flags发生时回调event_handler,并以c为回调参数。

    event_add(&ev, NULL)
把ev注册到事件队列里面,第二个参数指定的是超时值,设定成NULL表示忽略这项设定。

    event_dispatch()
表示进入事件循环,当队列里任何一个文件描述符发生事件的时候就会执行回调函数。

 
---------------------------------
更多的参看
阅读(2222) | 评论(0) | 转发(0) |
0

上一篇:池[1]

下一篇:池[2]

给主人留下些什么吧!~~