在之前博文libevent之Reactor模式中,我们知道Reactor模式中一个重要的组件就是事件多路分发机制(event demultiplexer)。而在libevent中,对事件多路分发机制的支持依赖于操作系统支持的多路复用机制(select、poll、epoll等)。

eventop

  libevent定义了一个顶层的结构体eventop(event option),来抽象不同操作系统支持的多路复用机制:

 // <event_internal.h>
1 /** Structure to define the backend of a given event_base. */
struct eventop {
/** The name of this backend. */
const char *name;
/** Function to set up an event_base to use this backend. It should
* create a new structure holding whatever information is needed to
* run the backend, and return it. The returned pointer will get
* stored by event_init into the event_base.evbase field. On failure,
* this function should return NULL. */
void *(*init)(struct event_base *);
/** Enable reading/writing on a given fd or signal. 'events' will be
* the events that we're trying to enable: one or more of EV_READ,
* EV_WRITE, EV_SIGNAL, and EV_ET. 'old' will be those events that
* were enabled on this fd previously. 'fdinfo' will be a structure
* associated with the fd by the evmap; its size is defined by the
* fdinfo field below. It will be set to 0 the first time the fd is
* added. The function should return 0 on success and -1 on error.
*/
int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
/** As "add", except 'events' contains the events we mean to disable. */
int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);
/** Function to implement the core of an event loop. It must see which
added events are ready, and cause event_active to be called for each
active event (usually via event_io_active or such). It should
return 0 on success and -1 on error.
*/
int (*dispatch)(struct event_base *, struct timeval *);
/** Function to clean up and free our data from the event_base. */
void (*dealloc)(struct event_base *);
/** Flag: set if we need to reinitialize the event base after we fork.
*/
int need_reinit;
/** Bit-array of supported event_method_features that this backend can
* provide. */
enum event_method_feature features;
/** Length of the extra information we should record for each fd that
has one or more active events. This information is recorded
as part of the evmap entry for each fd, and passed as an argument
to the add and del functions above.
*/
size_t fdinfo_len;
};

  可以看到,该结构体已经声明(非定义)了多路分发机制常备的Reactor初始化、事件添加、事件移除、事件分发及Reactor清理函数,而且均以函数指针的方式定义,便于复用。

  如epoll对该结构体的一个复用:

 static void *epoll_init(struct event_base *);
static int epoll_dispatch(struct event_base *, struct timeval *);
static void epoll_dealloc(struct event_base *); static const struct eventop epollops_changelist = {
"epoll (with changelist)",
epoll_init,
event_changelist_add,
event_changelist_del,
epoll_dispatch,
epoll_dealloc,
, /* need reinit */
EV_FEATURE_ET|EV_FEATURE_O1,
EVENT_CHANGELIST_FDINFO_SIZE
};

实际调用的多路复用机制

  libevent用了一个数组来存储其所支持的多路复用机制:

 // <event.c>
/* Array of backends in order of preference. */
static const struct eventop *eventops[] = {
#ifdef _EVENT_HAVE_EVENT_PORTS
&evportops,
#endif
#ifdef _EVENT_HAVE_WORKING_KQUEUE
&kqops,
#endif
#ifdef _EVENT_HAVE_EPOLL
&epollops,
#endif
#ifdef _EVENT_HAVE_DEVPOLL
&devpollops,
#endif
#ifdef _EVENT_HAVE_POLL
&pollops,
#endif
#ifdef _EVENT_HAVE_SELECT
&selectops,
#endif
#ifdef WIN32
&win32ops,
#endif
NULL
};

  通过这个程序,我们可以知道libevent是通过宏定义来确定当前操作系统是否支持某中多路复用机制,并且按顺序选择系统支持的机制。

  另外,我们如果想知道程序当前所支持的多路复用机制,我们可以调用函数event_get_supported_methods:

 // <event.c>
const char **
event_get_supported_methods(void)
{
static const char **methods = NULL;
const struct eventop **method;
const char **tmp;
int i = , k; /* count all methods */
for (method = &eventops[]; *method != NULL; ++method) {
++i;
} /* allocate one more than we need for the NULL pointer */
tmp = mm_calloc((i + ), sizeof(char *));
if (tmp == NULL)
return (NULL); /* populate the array with the supported methods */
for (k = , i = ; eventops[k] != NULL; ++k) {
tmp[i++] = eventops[k]->name;
}
tmp[i] = NULL; if (methods != NULL)
mm_free((char**)methods); methods = tmp; return (methods);
}

  而要想知道程序实际调用的是哪一种多路复用机制,我们可以调用函数event_get_method得到:

 // <event.c>
const char *
event_get_method(void)
{
return (current_base->evsel->name);
}

libevent之eventop的更多相关文章

  1. libevent源码分析:eventop

    eventop:定义了event_base使用的后端IO复用的一个统一接口 /** Structure to define the backend of a given event_base. */ ...

  2. Libevent的IO复用技术和定时事件原理

    Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...

  3. Libevent初探

    Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...

  4. libevent源码分析:time-test例子

    time-test例子是libevent自带的一个例子,通过libevent提供的定时事件来实现,间隔固定时间打印的功能. /* * gcc -g -o time-test time-test.c - ...

  5. 【转】libevent源码分析

    libevent源码分析 转自:http://www.cnblogs.com/hustcat/archive/2010/08/31/1814022.html 这两天没事,看了一下Memcached和l ...

  6. libevent源码分析(一)

    分析libevent的源代码,我的想法的是先分析各种结构体,struct event_base.struct event,然后是event_base_new函数.event_new函数.event_a ...

  7. libevent源码深度剖析

    原文地址: http://blog.csdn.net/sparkliang/article/details/4957667 第一章 1,前言 Libevent是一个轻量级的开源高性能网络库,使用者众多 ...

  8. libevent+bufferevent总结

    libevent+bufferevent总结 1 学习参考网址 libevent学习网址:http://blog.csdn.net/feitianxuxue/article/details/93725 ...

  9. 使用 libevent 和 libev 提高网络应用性能——I/O模型演进变化史

    构建现代的服务器应用程序需要以某种方法同时接收数百.数千甚至数万个事件,无论它们是内部请求还是网络连接,都要有效地处理它们的操作. 有许多解决方案,但事件驱动也被广泛应用到网络编程中.并大规模部署在高 ...

随机推荐

  1. Django 缓存模块 page_cache 源码阅读

    Django cache中比较常用的有 cache_page 这么个 decorators, 下面就根据请求流程,结合源码来说说它是怎么工作的? 版本是django1.8,不同版本可能函数等会变化,逻 ...

  2. SQL实例整理

    本文适合将w3school的SQL教程(http://www.w3school.com.cn/sql/sql_create_table.asp)都基本看过一遍的猿友阅读. 说说博主的情况吧.毕业找工作 ...

  3. CentOS7下安装GitLab

    三步在CentOS7系统下,完成GitLab的安装. 1.安装和配置必须的依赖 sudo yum install curl policycoreutils openssh-server openssh ...

  4. Android app内存管理的16点建议

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiopshared memory(共享内存) Android通过下面几个方式在不同的Process中来共享RAM: 每一个app的proc ...

  5. Android N(7.0) 被美翻的新特性!

    Tamic 专注移动开发!更多文章请关注 Csdn: http://blog.csdn.net/sk719887916/article/details/52612444 $ http://www.ji ...

  6. Python Generator 运行细节验证

    今天来__next__和send, 改天来throw和close class A: def __setattr__(self, key, val): print('set %s to %s'%(key ...

  7. [ExtJS5学习笔记]第三十四节 sencha extjs 5 grid表格之java后台导出excel

    继上次使用js前端导出excel之后,还有一个主要大家比较关注的是后台实现导出excel,因为本人开发使用的java所以这里使用apache的开源项目poi进行后台excel的导出. 本文目录 本文目 ...

  8. 磁盘管理,磁盘挂在mount,挂载光盘镜像文件,挂在U盘,umount 卸载命令, dd

    1 mount 命令格式: mount[-t vfstype] -o options device dir 其中: *-t vfstype 指定文件系统的类型,通常不必指定.mount会自动选择正确的 ...

  9. Java基本语法-----java流程控制语句

    1顺序语句 语句:使用分号分隔的代码称作为一个语句. 注意:没有写任何代码只是一个分号的时候,也是一条语句,称作空语句. 顺序语句就是按照从上往下的顺序执行的语句. 2判断(if-else) 在我们找 ...

  10. ORACLE数据库学习之备份与恢复

     oracle数据库的备份与恢复 第一部分:数据库的备份 备份的必要性 因为各种人为或外界的因素可能会造成数据库中灾难性的数据丢失,为了保证数据库中数据的安全,必须采取备份措施保证RDBMS中包含 ...