分类:
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,并且是线程安全的。