libevent基于事件驱动,event是他整个库的核心
event的作用:相当于Reactor框架中的事件处理程序组件,它提供了函数接口,供Reactor在事件发生时调用,以执行相应的事件处理,通常他会绑定一个有效的句柄
struct event {
TAILQ_ENTRY (event) (ev_active_next);
TAILQ_ENTRY (event) (ev_next);//
int min_heap_idx; /* for managing timeouts */
struct event_base *ev_base;
evutil_socket_t ev_fd;
union {
/* used for io events */
struct {
TAILQ_ENTRY (event) (ev_io_next);
struct timeval ev_timeout;
} ev_io;
/* used by signal events */
struct {
TAILQ_ENTRY (event) (ev_signal_next);
short ev_ncalls;
/* Allows deletes in callback */
short *ev_pncalls;
} ev_signal;
} _ev;
short ev_events;//是event关注的事件类型,它主要包括输入输出时间,定时时间和信号
struct timeval ev_timeout;
int ev_pri; /* smaller numbers are higher priority */
/* allows us to adopt for different types of events */
void (*ev_closure)(struct event_base *, struct event *);
void (*ev_callback)(evutil_socket_t, short, void *arg);
void *ev_arg;
int ev_res; /* result passed to event callback */
int ev_flags;
};
关于该结构体的理解:
我并不会对每一个都去解释有的显而易见的或者包含的我就不说了
每当有时间event转变为就绪状态时,libevent就会把它移入到active eventlist[priority] (个人理解是可以把event看成一个结点,然后总共有三条链表,一条代表活跃,一条是信号的,一条是输入输出的而在结构体中的ev_next,ev_active_next和ev_signal_next分别表示了在I/0事件链表中,在信号链表中,在激活链表中的位置)中,其中priority是event的优先级,接着libevent会根据自己的调度策略选择就绪事件,调用其cb_callback()函数执行事件处理;并根据就绪的句柄和时间类型填充cb_callback函数的参数
ev_base是该事件的反应堆,之后讨论
ev_fd对于I/O事件是绑定的文件描述符;对于signal时间是绑定的信号
ev_callback是event的回调函数
void(ev_callback)(int fd,short events,void arg);
fd对应于ev_fd,events对应于ev_events,arg对应于ev_arg(个人理解而言就相当于这个event结构体里面存储的是事件,和事件相应状态还有事件发生对应响应的函数)
ev_events;//是event关注的事件类型,它主要包括输入输出事件,定时事件和信号
ev_pri:代表事件优先级,越小则事件的优先级越高
ev_flag:标记event信息的字段,标明他的状态
ev_ncalls:事件就绪执行时候调用ev_callback的次数,通常1
ev_pncalls:指针,指向ev_ncalls或者是NULL(目前不懂为什么需要这个)
ev_res:记录了事件激活的类型
这个结构体其实代表的就是一个事件
关于这个结构体的函数:
这个结构体是一个事件,那么肯定有相应的操作将它添加到libevent中去
void event_set(struct event ev,int fd,short events,void (*callback)(int,short,void),void* arg)
void
event_set(struct event *ev, evutil_socket_t fd, short events,
void (*callback)(evutil_socket_t, short, void *), void *arg)
{
int r;
r = event_assign(ev, current_base, fd, events, callback, arg);
EVUTIL_ASSERT(r == 0);
}
1.设置事件ev绑定的文件描述符或者信号,对于定时事件设为-1即可
2.设置事件类型,比如EV_READ,EV_PERSIST,EV_WRITE,EV_SIGNAL等,
3.设置事件回调函数以及参数arg
4.初始化其他字段,比如缺省的event_base和优先级
int event_base_set(struct event_base base,struct event ev)
int
event_base_set(struct event_base *base, struct event *ev)
{
/* Only innocent events may be assigned to a different base */
if (ev->ev_flags != EVLIST_INIT)
return (-1);
_event_debug_assert_is_setup(ev);
ev->ev_base = base;
ev->ev_pri = base->nactivequeues/2;
return (0);
}
设置event_ev将要注册到的event_base
libevent有一个全局event_base指针current_base,默认情况下会被注册到current_base上,使用该函数可以指定不同的event_base
如果一个进程中存在多个libevent实例,则必须调用该函数为event设置不同的event_base
int event_priority_set(struct event* ev,int pri);
int
event_priority_set(struct event *ev, int pri)
{
_event_debug_assert_is_setup(ev);
if (ev->ev_flags & EVLIST_ACTIVE)
return (-1);
if (pri < 0 || pri >= ev->ev_base->nactivequeues)
return (-1);
ev->ev_pri = pri;
return (0);
}
设置优先级