Libevent源码剖析:event结构体
event结构体Libevent 对 event的管理事件设置的接口函数
event_base创建和初始化接口函数
libevnt中的事件处理器是event结构类型,主要封装了局柄,事件类型,回调函数,以及其他必要的标志和数据。该结构体在include/event2/event_struct.h文件中定义
event结构体
struct event
{
#if 0
struct event_callback
{
TAILQ_ENTRY(event_callback
) evcb_active_next
;
short evcb_flags
;
ev_uint8_t evcb_pri
;
ev_uint8_t evcb_closure
;
union {
void (*evcb_callback
)(evutil_socket_t
, short, void *);
void (*evcb_selfcb
)(struct event_callback
*, void *);
void (*evcb_evfinalize
)(struct event
*, void *);
void (*evcb_cbfinalize
)(struct event_callback
*, void *);
} evcb_cb_union
;
void *evcb_arg
;
};
#endif
struct event_callback ev_evcallback
;
union {
TAILQ_ENTRY(event
) ev_next_with_common_timeout
;
int min_heap_idx
;
} ev_timeout_pos
;
evutil_socket_t ev_fd
;
struct event_base
*ev_base
;
union {
struct {
LIST_ENTRY
(event
) ev_io_next
;
struct timeval ev_timeout
;
} ev_io
;
struct {
LIST_ENTRY
(event
) ev_signal_next
;
short ev_ncalls
;
short *ev_pncalls
;
} ev_signal
;
} ev_
;
#if 0
Libevent使用IO事件队列具有相同文件描述符的事件处理器组织在一起。当fd上有就绪事件,事件多路分发器
(epoll)将相关事件添加到活动事件队列中。信号事件队列的存在也是由于相同的原因
#endif
short ev_events
;
#if 0
#define EV_TIMEOUT 0x01
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PRESIST 0x10
#endif
short ev_res
;
struct timeval ev_timeout
;
};
Libevent 对 event的管理
libevent对event的管理主要从三个链表指针出发,每次有事件转变为就绪状态事件时,将其移至evcb_active_next队列中,调用其evcb_callback回调函数处理并且根据就绪fd和事件类型填充evcb_callback函数的参数
事件设置的接口函数
创建event对象:libevent提供的函数有 : event_set(),event_base_set(), event_priority_set()
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.fd 文件描述符或者信号,定时事件为-1; 2.设置事件类型比如EV_READ|EV_PERSIST 等等 3.设置事件的回调以及参数arg 4.初始化其他字段,比如缺省的event_base和优先级
event_base_set(struct event_base
*base
, struct event
*ev
)
{
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将要注册到event_base中; 如果一个进程中存在多个libevent实例,那么必须调用该函数为event设置不同的event_base
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);
}
event_base
struct event_base
{
const struct eventop
*evsel
;
void *evbase
;
#if 0
添加事件时的调用行为:evsel
->add(evbase
, ev
),实际上执行操作的是evbase;evsel指向全局变量
static const struct eventop
*eventops
[]中的一个
struct eventop
{
const char *name
;
void *(*init
)(struct event_base
*);
int (*add
)(struct event_base
*, evutil_socket_t fd
, short old
, short events
, void *fdinfo
);
int (*del
)(struct event_base
*, evutil_socket_t fd
, short old
, short events
, void *fdinfo
);
int (*dispatch
)(struct event_base
*, struct timeval
*);
void (*dealloc
)(struct event_base
*);
int need_reinit
;
enum event_method_feature features
;
size_t fdinfo_len
;
};
#endif
struct event_changelist changelist
;
const struct eventop
*evsigsel
;
struct evsig_info sig
;
int virtual_event_count
;
int virtual_event_count_max
;
int event_count
;
int event_count_max
;
int event_count_active
;
int event_count_active_max
;
int event_gotterm
;
int event_break
;
int event_continue
;
int event_running_priority
;
int running_loop
;
int n_deferreds_queued
;
struct evcallback_list
*activequeues
;
int nactivequeues
;
struct evcallback_list active_later_queue
;
struct common_timeout_list
**common_timeout_queues
;
int n_common_timeouts
;
int n_common_timeouts_allocated
;
struct event_io_map io
;
struct event_signal_map sigmap
;
struct min_heap timeheap
;
struct timeval tv_cache
;
struct evutil_monotonic_timer monotonic_timer
;
struct timeval tv_clock_diff
;
time_t last_updated_clock_diff
;
#ifndef EVENT__DISABLE_THREAD_SUPPORT
unsigned long th_owner_id
;
void *th_base_lock
;
void *current_event_cond
;
int current_event_waiters
;
#endif
struct event_callback
*current_event
;
#ifdef _WIN32
struct event_iocp_port
*iocp
;
#endif
enum event_base_config_flag flags
;
struct timeval max_dispatch_time
;
int max_dispatch_callbacks
;
int limit_callbacks_after_prio
;
int is_notify_pending
;
evutil_socket_t th_notify_fd
[2];
struct event th_notify
;
int (*th_notify_fn
)(struct event_base
*base
);
struct evutil_weakrand_state weakrand_seed
;
LIST_HEAD(once_event_list
, event_once
) once_events
;
};
创建和初始化
创建了一个event_base对象也即使创建了一个libevent实例,通过调用event_init()内部调用event_base_new函数执行创建, 为event_base申请空间,初始化timer mini-heap,选择合适的系统IO的demultiplexer机制,初始化各种事件链表 函数还检测系统的时间设置,为后面的时间管理打下基础
接口函数
注册事件 函数原型:
int
event_add(struct event
*ev
, const struct timeval
*tv
)
{
int res
;
if (EVUTIL_FAILURE_CHECK(!ev
->ev_base
)) {
event_warnx("%s: event has no event_base set.", __func__);
return -1;
}
EVBASE_ACQUIRE_LOCK(ev
->ev_base
, th_base_lock
);
res
= event_add_nolock_(ev
, tv
, 0);
EVBASE_RELEASE_LOCK(ev
->ev_base
, th_base_lock
);
return (res
);
}
删除事件原型为:int event_del(struct event *ev); 删除事件ev,对于IO事件,从IOdemultiplexer上将事件注销;对于Signal来说,将其从Signal事件链表中删除;对于定时事件,将从堆上删除(删除操作不一定是原子操作,比如删除事件之后,有可能从系统的IO机制中注销失败)
static int
event_del_(struct event
*ev
, int blocking
)
{
int res
;
struct event_base
*base
= ev
->ev_base
;
if (EVUTIL_FAILURE_CHECK(!base
)) {
event_warnx("%s: event has no event_base set.", __func__);
return -1;
}
EVBASE_ACQUIRE_LOCK(base
, th_base_lock
);
res
= event_del_nolock_(ev
, blocking
);
EVBASE_RELEASE_LOCK(base
, th_base_lock
);
return (res
);
}
int
event_del(struct event
*ev
)
{
return event_del_(ev
, EVENT_DEL_AUTOBLOCK
);
}
**总结:**分析了event_base这一重要结构体,初步看到了系统的IO复用机制的封装event_op结构,并且结合了源码堆注册和删除事件处理