Chinaunix首页 | 论坛 | 博客
  • 博客访问: 277938
  • 博文数量: 46
  • 博客积分: 2021
  • 博客等级: 大尉
  • 技术积分: 406
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-03 13:00
文章分类

全部博文(46)

文章存档

2011年(1)

2010年(9)

2009年(2)

2007年(13)

2006年(21)

我的朋友

分类:

2010-04-02 10:32:06

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; ///<标志位  

}; 

 

举例:epoll.c中用来描述epoll

const struct eventop epollops = {

        "epoll",

        epoll_init,

        epoll_add,

        epoll_del,

        epoll_dispatch,

        epoll_dealloc,

        1 /* need reinit */

};

 

struct event_base {   

    const struct eventop *evsel;   ///<事件驱动引擎  

    void *evbase;                 //用于保存不同的引擎的数据结构,如epoll,select等不同引擎的数据结构.  

    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将定时器队列实现为一个最小堆,也就是为了每次都把时间最晚的定时器能取出来,然后实现超时。更其实算法很简单,想要详细的了解可以去看下算法导论的第六章的Priority queues.  

 

    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;  

};

 

struct event_base* event_init  (void) 

初始化event API.
event API必须使用event_init初始化后才能使用。

event_init函数中使用event_base_new()创建一个新的struct event_base。使用全局变量current_base指向刚创建event_base。

 

struct event_base* event_base_new  (void)

初始化event API

使用event_base_new初始化一个新的event base, 不设置全局变量current_base.

如果使用event_base_new, 则每增加一个新的事件到event base后,调用event_base_set

 

event_base_new函数中设置evbase变量, evbase指向具体的事件引擎的数据结构。

linux 2.6内核evbase为struct epollop

设置evsel为:

const struct eventop epollops = {

        "epoll",

        epoll_init,

        epoll_add,

        epoll_del,

        epoll_dispatch,

        epoll_dealloc,

        1 /* need reinit */

};

 

int event_priority_init  (int) 

设定有几种优先级队列。默认libevent中都是用一种相同的队列,可以根据自己的需要设定不同的优先级队列,数字小的优先级队列优先于数字大的队列。

 

int event_base_priority_init  (struct event_base *  , int)

和event_priority_init一样,唯一区别在于event_priority_init设置全局变量current_base,而event_base_priority_init设定制定的event_base

 

void

event_set(struct event *ev, int fd, short events,

          void (*callback)(int, short, void *), void *arg)

用于生成事件结构体ev,以备event_add()和event_del()使用.事件驱动程序将会调用void (*fn)(int, short, void *)中fn指定的函数,并传递三个参数int:文件描述符,short:事件类型,void*:其它参数由arg参数指定.

 

int fd 指定要监视的文件描述符,

 

short event 可以是EV_READ,EV_WRITE或EV_READ|EV_WRITE表示该文件可以无阻塞地进行读写.

 

fn函数将会被调用,并传递给三个变量:

 

int fd:触发事件的文件描述符.

 

short event:触发事件的类型EV_TIMEOUT,EV_SIGNAL, EV_READ, or EV_WRITE.

 

void* :由arg参数指定的变量.

 

另外重复注册的事件将会产生重复的事件通知.EV_PERSIST可以让注册的事件在执行完后不被删除,直到调用event_del()删除.

 

结构体初始化完成后,在无需改变内容的情况下,可以被event_add(),event_del()重复使用.但是当结构体被event_add()添加之后,必须保持结构体的内容,直到事件被执行后退出或调用event_del()删除该事件.不允许将这个结构体变量注册完事件后重复使用.每一个描述符都需要一个单独的event结构体变量.

 

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

event_add()函数使通过event_set()设置的事件在事件匹配或超时时(如果设置了超时)被执行.

 

event结构体变量必须先用event_set()初始化过,并且在事件被删除前不得再次调用event_set()来初始化之.如果事件发生超时,旧的超时时间会被新的超时时间所取代.

 

int event_del(struct event *ev)

event_del()函数会取消event结构体所指定的事件,如果该事件已经执行或没有注册(在事件链表中不存在),该函数不会产生任何作用.

 

int event_base_loop(struct event_base *base, int flags)

loop函数将进入事件监测循环。

 

int event_base_loopbreak(struct event_base *event_base)

立即终止event_loop

 

int event_base_loopexit(struct event_base *event_base, const struct timeval *tv)

当指定的时间到达后,终止event_loop

 

int event_dispatch (void) 

和event_loop作用是一样的。

 

int event_once  ( int  , 

  short  , 

  void(*)(int, short, void *)  , 

  void *  , 

  const struct timeval *    

 )

类似event_set函数,event_once设置的事件只会被处理一次。event_once函数设置全局的current_base变量。可以使用event_base_once函数设定自定义的event_base,并且是线程安全的。

 

 

阅读(1499) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~