Libevent(2.1.8)中的事件结构和管理
Libevent(2.1.8)中的事件结构体
这里的libevent版本为 2.1.8 。 libevent中事件的结构体struct event,定义在event_struct.h 中, 这里我们简单看一下:
struct event {
struct event_callback ev_evcallback; //事件的回调函数 /* for managing timeouts */
union {
TAILQ_ENTRY(event) ev_next_with_common_timeout;// 链表形式管理定时 之前只用最小堆管理超时
int min_heap_idx; //最小堆 管理超时事件
} ev_timeout_pos;// 二选一
evutil_socket_t ev_fd; // io事件时为关心的文件描述符,信号事件时为信号值 struct event_base *ev_base;// 所属事件堆的实例 union {
/* used for io events */
struct {
LIST_ENTRY (event) ev_io_next;
struct timeval ev_timeout;
} ev_io; //这部分指io事件时 所关心的同一描述符下,所有IO事件的链表 /* used by signal events */
struct {
LIST_ENTRY (event) ev_signal_next;
short ev_ncalls;
/* Allows deletes in callback */
short *ev_pncalls;
} ev_signal;//同一信号下信号事件链表
} ev_; short ev_events; //事件的类型 可读可写 超时等
short ev_res; /* result passed to event callback */
struct timeval ev_timeout; //事件超时时间
};
这里可以看到这个版本下的event 结构体比之前的好像少了不少东西, 如之前的结构:
//event提供了函数接口,供Reactor在事件发生时调用,以执行相应的事件处理,
//通常它会绑定一个有效的句柄(ev_fd)做为回调函数的参数.
struct event {
//已注册事件队列入口
TAILQ_ENTRY (event) ev_next;
//已激活事件队列入口
TAILQ_ENTRY (event) ev_active_next;
//信号事件队列入口 不过在以前的分析中可以看到,将来这个队列中的内容会被添加到ev_active_next队列中。
TAILQ_ENTRY (event) ev_signal_next;
//表示该event在定时器事件最小堆min_heap的索引
unsigned int min_heap_idx; /* for managing timeouts */
//该事件所属的反应堆实例
struct event_base *ev_base;
//对于I/O事件,是绑定的文件描述符; 对于signal事件,是绑定的信号.
int ev_fd; //表示事件类型: I/O,定时器或者信号
short ev_events; //事件就绪执行时,将要调用ev_callback 的次数,通常为1
short ev_ncalls; //该事件的超时时间,在定时器最小堆min_heap操作中作为节点值进行比较.
struct timeval ev_timeout; //该事件的优先级,越小越优先.
int ev_pri; /* smaller numbers are higher priority */ //该事件被激活时的回调函数
void (*ev_callback)(int, short, void *arg); //该事件的标记信息,表示其当前的状态,即它在哪个链表中
int ev_flags; ... //其他成员.
};
这里可以看到在老版本的libevent 中event结构体中有回调函数, 参数,优先级参数, 新版本中都被定义在了struct event_callback ev_evcallback;中 如下:
struct event_callback {
TAILQ_ENTRY(event_callback) evcb_active_next;
short evcb_flags; //选择回调类型 由以下四种
ev_uint8_t evcb_pri; /* smaller numbers are higher priority */
ev_uint8_t evcb_closure;
/* allows us to adopt for different types of events */
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;
};
比起老版本 新版本又丢弃了TAILQ_ENTRY(event) ev_next; 已注册事件队列入口 ev_active_next 已激活队列入口 ev_signal_next 信号事件队列入口等结构。
Libevent 事件堆实例结构体:
新版本的struct base_event 如下:
struct event_base {
/** Function pointers and other data to describe this event_base's
* backend. */
const struct eventop *evsel;//具体事件处理模型结构(select /poll/epoll)指针
/** Pointer to backend-specific data. */
void *evbase;//指向IO复用的真正操作 通过evsel来初始化 /** 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; //??????后续
/** Maximum number of virtual events active */
int virtual_event_count_max; //?????
/** Number of total events added to this event_base */
int event_count; //事件总数
/** Maximum number of total events added to this event_base */
int event_count_max;//事件堆最多的事件数量
/** Number of total events active in this event_base */
int event_count_active;
/** Maximum number of total events active in this event_base */
int event_count_active_max; /** 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; //当前running 事件的优先级 /** Set if we're running the event_base_loop function, to prevent
* reentrant invocation. */
int running_loop; //是否正在loop event /** Set to the number of deferred_cbs we've made 'active' in the
* loop. This is a hack to prevent starvation; it would be smarter
* to just use event_config_set_max_dispatch_interval's max_callbacks
* feature */
int n_deferreds_queued; /* Active event management. */
/** An array of nactivequeues queues for active event_callbacks (ones
* that have triggered, and whose callbacks need to be called). Low
* priority numbers are more important, and stall higher ones.
*/
//已激活的回调事件队列 即event_callback 结构的队列
struct evcallback_list *activequeues;
/** The length of the activequeues array */
int nactivequeues; //激活队列长度
/** A list of event_callbacks that should become active the next time
* we process events, but not this time. */
struct evcallback_list active_later_queue;// 下次激活的事件队列? /* 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; /** Mapping from file descriptors to enabled (added) events */
struct event_io_map io;//存储io 事件 /** Mapping from signal numbers to enabled (added) events. */
struct event_signal_map sigmap;//存储信号事件 /** 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; struct evutil_monotonic_timer monotonic_timer; /** 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; #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;
/** 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
/** The event whose callback is executing right now */
struct event_callback *current_event; /** Flags that this base was configured with */
//这里后续的event config 会讲到
enum event_base_config_flag flags; struct timeval max_dispatch_time;
int max_dispatch_callbacks;
int limit_callbacks_after_prio; /* Notify main thread to wake up break, etc. */
//多线程 主线程loop过程中一般会阻塞
//若这时添加或者删除事件的话, 就需要唤醒阻塞的主线程, 加入了一个未决状态
/** 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);//唤醒主线程的函数指针 /** Saved seed for weak random number generator. Some backends use
* this to produce fairness among sockets. Protected by th_base_lock. */
struct evutil_weakrand_state weakrand_seed; /** List of event_onces that have not yet fired. */
LIST_HEAD(once_event_list, event_once) once_events; };
对于事件的存储 老版本中用队列来存储, 在新版本中使用哈希表map 如event_io_map , event_signal_map结构。还有一些多线程支持的参数后续会看到它们的用途。后续还会详细解释其中的各个字段含义。
Libevent(2.1.8)中的事件结构和管理的更多相关文章
- libevent中的事件机制
libevent是事件驱动的网络库,事件驱动是他的核心,所以理解事件驱动对于理解整个网络库有很重要的意义. 本着从简入繁,今天分析下单线程最简单的事件触发.通过sample下的event- ...
- libevent源码分析二--timeout事件响应
libevent不仅支持io事件,同时还支持timeout事件与signal事件,这篇文件将分析libevent是如何组织timeout事件以及如何响应timeout事件. 1. min_heap ...
- libevent源码分析一--io事件响应
这篇文章将分析libevent如何组织io事件,如何捕捉事件的发生并进行相应的响应.这里不会详细分析event与event_base的细节,仅描述io事件如何存储与如何响应. 1. select l ...
- 怎么理解js中的事件委托
怎么理解js中的事件委托 时间 2015-01-15 00:59:59 SegmentFault 原文 http://segmentfault.com/blog/sunchengli/119000 ...
- jQuery:详解jQuery中的事件(二)
上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 接上篇jQuery:详解jQuery中的事件(一) ...
- jQuery学习笔记(三)jQuery中的事件
目录 加载DOM 事件绑定 合成事件 事件冒泡 移除事件 一.加载DOM Javascript 与HTML之间的交互是通过用户操作浏览器页面引发的事件来处理的.jQuery提供了丰富的事件处理机制.从 ...
- JS 中的事件绑定、事件监听、事件委托
事件绑定 要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数.所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称. 在JavaScript中,有 ...
- javascript 中的事件机制
1.javascript中的事件. 事件流 javascript中的事件是以一种流的形式存在的. 一个事件会也有多个元素同时响应. 有时候这不是我们想要的效果, 我们只是需要某个特定的元素相应我们的绑 ...
- jQuery中的事件与动画 (你的明天Via Via)
众所周知,页面在加载时,会触发load事件:当用户单击某个按钮时,会触发该按钮的click事件. 这些事件就像日常生活中,人们按下开关,灯就亮了(或者灭了),往游戏机里投入游戏币就可以启动游戏一样, ...
随机推荐
- 项目总结一:响应式之CSS3 媒体查询
1.<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scala ...
- Ubuntu远程登陆、SSH图形界面、WOL远程唤醒
本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 实现目标:通过路由器配置路由路径,将拨号获取的公网IP地址指向局域网Ubuntu服务器.家里有 ...
- javascript高性能写法
看到一篇不错的博文,如果想写出比较高性能的代码,可参看这个链接http://developer.51cto.com/art/200906/131335.htm
- 视觉词袋模型(BOVW)
一.介绍 Bag-of-words model (BoW model) 最早出现在神经语言程序学(NLP)和信息检索(IR)领域. 该模型忽略掉文本的语法和语序, 用一组无序的单词(words)来表达 ...
- 关于NIM博弈结论的证明
关于NIM博弈结论的证明 NIM博弈:有k(k>=1)堆数量不一定的物品(石子或豆粒…)两人轮流取,每次只能从一堆中取若干数量(小于等于这堆物品的数量)的物品,判定胜负的条件就是,最后一次取得人 ...
- 【Win 10 应用开发】UI Composition 札记(三):与 XAML 集成
除了 DirectX 游戏开发,我们一般很少单独使用 UI Composition ,因此,与 XAML 互动并集成是必然结果.这样能够把两者的优势混合使用,让UI布局能够更灵活. 说到与 XAML ...
- 蓝桥杯之K好数
如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数.求L位K进制数中K好数的数目.例如K = 4,L = 2的时候,所有K好数为11.13.20.22.30.3 ...
- luogu P1563 玩具谜题
https://www.luogu.org/problemnew/show/1563 题目: 小南有一套可爱的玩具小人, 它们各有不同的职业. 有一天, 这些玩具小人把小南的眼镜藏了起来. 小南发现玩 ...
- dubbo专题」dubbo其实很简单,就是一个远程服务调用的框架(1)
一.dubbo是什么? 1)本质:一个Jar包,一个分布式框架,,一个远程服务调用的分布式框架. 既然是新手教学,肯定很多同学不明白什么是分布式和远程服务调用,为什么要分布式,为什么要远程调用.我简单 ...
- 经典面试题: 从输入URL到页面加载的过程发生了什么?
可以分为这几个大的过程: DNS解析 TCP连接 客户端发送HTTP请求 服务器处理请求并返回HTTP报文 浏览器解析渲染页面 结束 其中(1)DNS解析可以理解为主寻找这个IP地址的过程,其中如果找 ...