首页 技术 正文
技术 2022年11月18日
0 收藏 386 点赞 2,176 浏览 7570 个字

  event_base是libevent的事务处理框架,负责事件注册、删除等,属于Reactor模式中的Reactor。

event_base结构体

  event_base结构体定义于<event_internal.h>中:

 struct event_base {
/** Function pointers and other data to describe this event_base's
* backend. */
const struct eventop *evsel;
/** Pointer to backend-specific data. */
void *evbase; /** List of changes to tell backend about at next dispatch. Only used
* by the O(1) backends. */
struct event_changelist changelist; /** Function pointers used to describe the backend that this event_base
* uses for signals */
const struct eventop *evsigsel;
/** Data to implement the common signal handelr code. */
struct evsig_info sig; /** Number of virtual events */
int virtual_event_count;
/** Number of total events added to this event_base */
int event_count;
/** Number of total events active in this event_base */
int event_count_active; /** Set if we should terminate the loop once we're done processing
* events. */
int event_gotterm;
/** Set if we should terminate the loop immediately */
int event_break;
/** Set if we should start a new instance of the loop immediately. */
int event_continue; /** The currently running priority of events */
int event_running_priority; /** Set if we're running the event_base_loop function, to prevent
* reentrant invocation. */
int running_loop; /* Active event management. */
/** An array of nactivequeues queues for active events (ones that
* have triggered, and whose callbacks need to be called). Low
* priority numbers are more important, and stall higher ones.
*/
struct event_list *activequeues;
/** The length of the activequeues array */
int nactivequeues; /* common timeout logic */ /** An array of common_timeout_list* for all of the common timeout
* values we know. */
struct common_timeout_list **common_timeout_queues;
/** The number of entries used in common_timeout_queues */
int n_common_timeouts;
/** The total size of common_timeout_queues. */
int n_common_timeouts_allocated; /** List of defered_cb that are active. We run these after the active
* events. */
struct deferred_cb_queue defer_queue; /** Mapping from file descriptors to enabled (added) events */
struct event_io_map io; /** Mapping from signal numbers to enabled (added) events. */
struct event_signal_map sigmap; /** All events that have been enabled (added) in this event_base */
struct event_list eventqueue; /** Stored timeval; used to detect when time is running backwards. */
struct timeval event_tv; /** Priority queue of events with timeouts. */
struct min_heap timeheap; /** Stored timeval: used to avoid calling gettimeofday/clock_gettime
* too often. */
struct timeval tv_cache; #if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
/** Difference between internal time (maybe from clock_gettime) and
* gettimeofday. */
struct timeval tv_clock_diff;
/** Second in which we last updated tv_clock_diff, in monotonic time. */
time_t last_updated_clock_diff;
#endif #ifndef _EVENT_DISABLE_THREAD_SUPPORT
/* threading support */
/** The thread currently running the event_loop for this base */
unsigned long th_owner_id;
/** A lock to prevent conflicting accesses to this event_base */
void *th_base_lock;
/** The event whose callback is executing right now */
struct event *current_event;
/** A condition that gets signalled when we're done processing an
* event with waiters on it. */
void *current_event_cond;
/** Number of threads blocking on current_event_cond. */
int current_event_waiters;
#endif #ifdef WIN32
/** IOCP support structure, if IOCP is enabled. */
struct event_iocp_port *iocp;
#endif /** Flags that this base was configured with */
enum event_base_config_flag flags; /* Notify main thread to wake up break, etc. */
/** True if the base already has a pending notify, and we don't need
* to add any more. */
int is_notify_pending;
/** A socketpair used by some th_notify functions to wake up the main
* thread. */
evutil_socket_t th_notify_fd[];
/** An event used by some th_notify functions to wake up the main
* thread. */
struct event th_notify;
/** A function used to wake up the main thread from another thread. */
int (*th_notify_fn)(struct event_base *base);
};

  其中值得注意的是evsel和evbase。evsel指向了全局变量

static const struct eventop *eventops[]

中的一个元素,而evbase则实际执行多路复用机制的实例化。

  如果我们看函数event_base_new_with_config的定义就会比较清晰evsel和evbase之间的关系了:

 // <event.c>
1 struct event_base *
event_base_new_with_config(const struct event_config *cfg)
{
...... for (i = ; eventops[i] && !base->evbase; i++) {
if (cfg != NULL) {
/* determine if this backend should be avoided */
if (event_config_is_avoided_method(cfg,
eventops[i]->name))
continue;
if ((eventops[i]->features & cfg->require_features)
!= cfg->require_features)
continue;
} /* also obey the environment variables */
if (should_check_environment &&
event_is_method_disabled(eventops[i]->name))
continue; base->evsel = eventops[i]; base->evbase = base->evsel->init(base);
} ......
}

event_base创建及初始化

  创建event_base对象即是创建一个libevent实例。具体的创建函数是event_base_new:

 struct event_base *
event_base_new(void)
{
struct event_base *base = NULL;
struct event_config *cfg = event_config_new();
if (cfg) {
base = event_base_new_with_config(cfg);
event_config_free(cfg);
}
return base;
}

  由上边程序知道,event_base创建的关键所在是event_base_new_with_config函数,而此函数又通过调用多路调用机制的初始化函数来初始化event_base实例:

 // <event.c>
struct event_base *
event_base_new_with_config(const struct event_config *cfg)
{
...... for (i = ; eventops[i] && !base->evbase; i++) {
if (cfg != NULL) {
/* determine if this backend should be avoided */
if (event_config_is_avoided_method(cfg,
eventops[i]->name))
continue;
if ((eventops[i]->features & cfg->require_features)
!= cfg->require_features)
continue;
} /* also obey the environment variables */
if (should_check_environment &&
event_is_method_disabled(eventops[i]->name))
continue; base->evsel = eventops[i]; base->evbase = base->evsel->init(base);
} ......
}

  以epoll为例,其对event_base实例的初始化函数为:

 static void *
epoll_init(struct event_base *base)
{
int epfd;
struct epollop *epollop; /* Initialize the kernel queue. (The size field is ignored since
* 2.6.8.) */
if ((epfd = epoll_create()) == -) {
if (errno != ENOSYS)
event_warn("epoll_create");
return (NULL);
} evutil_make_socket_closeonexec(epfd); if (!(epollop = mm_calloc(, sizeof(struct epollop)))) {
close(epfd);
return (NULL);
} epollop->epfd = epfd; /* Initialize fields */
epollop->events = mm_calloc(INITIAL_NEVENT, sizeof(struct epoll_event));
if (epollop->events == NULL) {
mm_free(epollop);
close(epfd);
return (NULL);
}
epollop->nevents = INITIAL_NEVENT; if ((base->flags & EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST) != ||
((base->flags & EVENT_BASE_FLAG_IGNORE_ENV) == &&
evutil_getenv("EVENT_EPOLL_USE_CHANGELIST") != NULL))
base->evsel = &epollops_changelist; evsig_init(base); return (epollop);
} struct epollop {
struct epoll_event *events; //并发服务器--02(基于I/O复用——运用epoll技术)
int nevents;
int epfd;
};

接口函数

事件相关的常用接口函数

  1. event_new

  创建事件(涉及内存分配)。

  1. event_add

  添加事件到event_base。

  2. event_del

  将事件从监听列表(pending list)中移除。

  3. event_free

  释放由event_new创建的事件(内存)。从其定义可看出其与event_del的区别:

 void
event_free(struct event *ev)
{
_event_debug_assert_is_setup(ev); /* make sure that this event won't be coming back to haunt us. */
event_del(ev);
_event_debug_note_teardown(ev);
mm_free(ev); }

  3. event_callback_fn

  事件的回调函数,用于执行具体的I/O操作。其定义如下:

 /**
A callback function for an event. It receives three arguments: @param fd An fd or signal
@param events One or more EV_* flags
@param arg A user-supplied argument. @see event_new()
*/
typedef void (*event_callback_fn)(evutil_socket_t, short, void *);

超时和信号事件的特殊接口函数

  为了方便对超时和信号事件的处理,libevent特别为它们定义了接口函数(实际是对通用函数的封装)。

  超时事件:

 /**
@name evtimer_* macros Aliases for working with one-shot timer events */
/**@{*/
#define evtimer_assign(ev, b, cb, arg) \
event_assign((ev), (b), -, , (cb), (arg))
#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
#define evtimer_add(ev, tv) event_add((ev), (tv))
#define evtimer_del(ev) event_del(ev)
#define evtimer_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv))
#define evtimer_initialized(ev) event_initialized(ev)
/**@}*/

  信号事件:

 /**
@name evsignal_* macros Aliases for working with signal events
*/
/**@{*/
#define evsignal_add(ev, tv) event_add((ev), (tv))
#define evsignal_assign(ev, b, x, cb, arg) \
event_assign((ev), (b), (x), EV_SIGNAL|EV_PERSIST, cb, (arg))
#define evsignal_new(b, x, cb, arg) \
event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg))
#define evsignal_del(ev) event_del(ev)
#define evsignal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv))
#define evsignal_initialized(ev) event_initialized(ev)
/**@}*/ 

事件处理主循环

有待添加

参考资料

  libevent源码深度剖析六

  libevent源码深度剖析七

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,031
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,520
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,368
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,148
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,781
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,859