博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
libevent源码深度剖析十
阅读量:5735 次
发布时间:2019-06-18

本文共 2842 字,大约阅读时间需要 9 分钟。

转自:

libevent源码深度剖析十

——支持I/O多路复用技术

张亮

      Libevent的核心是事件驱动、同步非阻塞,为了达到这一目标,必须采用系统提供的I/O多路复用技术,而这些在Windows、Linux、Unix等不同平台上却各有不同,如何能提供优雅而统一的支持方式,是首要关键的问题,这其实不难,本节就来分析一下。

1 统一的关键

      Libevent支持多种I/O多路复用技术的关键就在于结构体eventop,这个结构体前面也曾提到过,它的成员是一系列的函数指针, 定义在event-internal.h文件中:

1 struct eventop {
2 const char *name; 3 void *(*init)(struct event_base *); // 初始化 4 int (*add)(void *, struct event *); // 注册事件 5 int (*del)(void *, struct event *); // 删除事件 6 int (*dispatch)(struct event_base *, void *, struct timeval *); // 事件分发 7 void (*dealloc)(struct event_base *, void *); // 注销,释放资源 8 /* set if we need to reinitialize the event base */ 9 int need_reinit; 10 };

 在libevent中,每种I/O demultiplex机制的实现都必须提供这五个函数接口,来完成自身的初始化、销毁释放;对事件的注册、注销和分发。

比如对于epoll,libevent实现了5个对应的接口函数,并在初始化时并将eventop的5个函数指针指向这5个函数,那么程序就可以使用epoll作为I/O demultiplex机制了。

2 设置I/O demultiplex机制

      Libevent把所有支持的I/O demultiplex机制存储在一个全局静态数组eventops中,并在初始化时选择使用何种机制,数组内容根据优先级顺序声明如下:

1 /* In order of preference */  2 static const struct eventop *eventops[] = {
3 #ifdef HAVE_EVENT_PORTS 4 &evportops, 5 #endif 6 #ifdef HAVE_WORKING_KQUEUE 7 &kqops, 8 #endif 9 #ifdef HAVE_EPOLL 10 &epollops, 11 #endif 12 #ifdef HAVE_DEVPOLL 13 &devpollops, 14 #endif 15 #ifdef HAVE_POLL 16 &pollops, 17 #endif 18 #ifdef HAVE_SELECT 19 &selectops, 20 #endif 21 #ifdef WIN32 22 &win32ops, 23 #endif 24 NULL 25 };

 然后libevent根据系统配置和编译选项决定使用哪一种I/O demultiplex机制,这段代码在函数event_base_new()中:

 

1 base->evbase = NULL; 2     for (i = 0; eventops[i] && !base->evbase; i++) {
3 base->evsel = eventops[i]; 4 base->evbase = base->evsel->init(base); 5 };

可以看出,libevent在编译阶段选择系统的I/O demultiplex机制,而不支持在运行阶段根据配置再次选择。

    以Linux下面的epoll为例,实现在源文件epoll.c中,eventops对象epollops定义如下:

 

1 const struct eventop epollops = {
2 "epoll", 3 epoll_init, 4 epoll_add, 5 epoll_del, 6 epoll_dispatch, 7 epoll_dealloc, 8 1 /* need reinit */ 9 };

变量epollops中的函数指针具体声明如下,注意到其返回值和参数都和eventop中的定义严格一致,这是函数指针的语法限制。

 

1 static void *epoll_init    (struct event_base *); 2 static int epoll_add    (void *, struct event *); 3 static int epoll_del    (void *, struct event *); 4 static int epoll_dispatch(struct event_base *, void *, struct timeval *); 5 static void epoll_dealloc    (struct event_base *, void *);

  那么如果选择的是epoll,那么调用结构体eventop的init和dispatch函数指针时,实际调用的函数就是epoll的初始化函数epoll_init()和事件分发函数epoll_dispatch()了;

     关于epoll的具体用法这里就不多说了,可以参见介绍epoll的文章(本人的哈哈):

 

 C++语言提供了虚函数来实现多态,在C语言中,这是通过函数指针实现的。对于各类函数指针的详细说明可以参见文章:

 
同样的,上面epollops以及epoll的各种函数都直接定义在了epoll.c源文件中,对外都是不可见的。对于libevent的使用者而言,完全不会知道它们的存在,对epoll的使用也是通过eventop来完成的,达到了信息隐藏的目的。

 

3 小节

 

    支持多种I/O demultiplex机制的方法其实挺简单的,借助于函数指针就OK了。通过对源代码的分析也可以看出,Libevent是在编译阶段选择系统的I/O demultiplex机制的,而不支持在运行阶段根据配置再次选择。

 

 

 

转载于:https://www.cnblogs.com/xinzaibing/archive/2012/03/01/2376359.html

你可能感兴趣的文章
Ubuntu 12.04 root用户登录设置
查看>>
存储过程点滴
查看>>
Maven编译跳过test的设置
查看>>
SQLyog图形化l数据库的操作和学习
查看>>
[LeetCode]22.Generate Parentheses
查看>>
WEB前端 CSS选择器
查看>>
计算A/B Test需要的样本量
查看>>
二叉树前序中序后序遍历的非递归方法
查看>>
mysql 行转列列转行
查看>>
《设计模式系列》---桥接模式
查看>>
[Unity3d]Shader 着色器 学习前了解知识
查看>>
Linux中文件颜色所代表的属性和颜色
查看>>
Redrain duilib中事件委托存在的问题
查看>>
43、我的C#学习笔记9
查看>>
网站建表实践及优化
查看>>
字符串的简单操作
查看>>
C#新功能--命名参数与可选参数
查看>>
strtok和strtok_r
查看>>
维辰超市:借助云商城成功转型新零售
查看>>
web.xml中<load-on-start>n</load-on-satrt>作用
查看>>