libev个人问题解惑
我们的游戏后端一直以来用的都是libev,之前尝试过去读源码,因为里面用了大量宏和自己也不够耐心的原因,一直没有看懂。这次终于痛下决心,一定要啃下它,于是在这个星期调整自己的工作学习方式(在读源码的过程也发现平时一些不利于学习的习惯),结合别人的文章与源码,终于看懂了它的脉络,然后解答了一些困惑我已久的问题,其它的细节部分再看就相对简单了。
libev是一个事件驱动库,可用select, poll, epoll等做为底层支持。关于如何选择的目前还不是很清楚,只知道它是根据对应宏是否定义来做出选择。比如epoll就要看EV_USE_EPOLL这个宏是否定义,但是EV_USE_EPOLL又依赖于宏HAVE_EPOLL_CTL和宏HAVE_SYS_EPOLL_H是否定义,这两个宏的位置我还没找到在哪里设置的,目前猜测是在生成makefile时通过检测系统环境动态生成。经过实验也知道了在linux下,libev默认使用的是epoll。
这里说下libev的主循环,libev的主循环在函数ev_run中,大致的流程是
检测是否有新事件加入或者老事件修改 ---> 有就通过底层调用epoll_ctl进行设置,没有则进入下一步 ---> 计算epoll_wait的time_out时间(其实里面还有个io_block时间貌似会先sleep,因为暂时涉及不到就先不关注) ---> 调用epoll_wait-->阻塞结束,处理所有发生的事件,然后回到第一步
在知道libev的底层在linux下是使用epoll以后,对于文件描述符的读写事件的实现,其实也就大概猜得到了。一直困惑于我的是libev的记时器是如何实现的,这里详细记录一下。
在libev中计时器的结构体是ev_timer,里面有两个比较重要的变量是after和repeat。after是指这个计时器第一次是多久之后触发;repeat是指第一次触发之后,多长周期再次触发。把定时器的回调、after、repeat设置好之后,就可以调用ev_timer_start开启计时器。libev对于一个ev_loop会维护一个包含所有计时器的最小堆,将距离此刻最近的计时器放在堆顶。在调用epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)函数之前,算出timeout = 计时器堆顶元素到期时刻 - 当前时刻,这样一来就实现了计时器的功能。计时器触发之后会根据是否存在repeat重新设置最小堆,如存在则修改触发时间并调整最小堆,如不存在则调用ev_timer_stop。
在了解了上面的知识后,我想到了一个问题,那要是在epoll_wait的阻塞期间我想加入一个新的ev_io或者ev_timer怎么办呢?按照上面的实现的实现方式是不可能实时检测到的。实际上这就是我想岔了,既然是事件驱动,那么在阻塞期间就说明没有事件发生,没有事件发生又怎么可能会产生新ev_io或ev_timer呢?哈哈哈哈,我老是会想到这些个奇怪的问题。
当然看源码到现在,了解的肯定不只这么点,这里只记录了点我个人的问题。如果要把libev的整个框架说完那么估计要写很长了。我也还没有看完,继续努力,继续学习。
最后附上我看源码时结合的文章链接:https://blog.csdn.net/drdairen/article/details/53785447
libev个人问题解惑的更多相关文章
- [译]libev和libevent的设计差异
本文译自what's the difference between libev and libevent? 作者是libev作者 [问]两个库都是为异步io调度而设计,在Linux上都是使用epoll ...
- CentOS 6.6安装Xtrabackup RPM提示缺少libev.so.4()
在CentOS Release 6.6安装percona-xtrabackup-2.3.4时,遇到下面错误信息 rpm -ivh percona-xtrabackup-2.3.4-1.el6.x86_ ...
- libev学习(一)
一.libev简介 Libev是一个事件循环:你注册感兴趣的特定事件(比如一个文件可以读取时或者发生超时时),它将管理这些事件源,将这些事件反馈给你的程序.为了实现这些,至少要在你的进程(或线程)中执 ...
- libev安装与示例程序编译运行
Linux平台C网络编程,之前总是看各大名著(如UNIX环境高级编程和UNIX网络编程,还有TCP/IP详解 卷1:协议和深入理解计算机系统(原书第2版)),同时写点小程序练习.然而还是拿不出手. 参 ...
- 001.libev安装及eclipse下添加libev库链接
libev库安装: 1.下载页面:http://dist.schmorp.de/libev/ 当前版本下载: [root@mid_server ~]# cd /usr/local/src [root ...
- [C#解惑] #2 对象的初始化顺序
谜题 在上一篇C#解惑中,我们提到了对象的初始化顺序.当我们创建一个子类的实例时,总是会先执行基类的构造函数,然后再执行子类的构造函数.那么实例字段是什么时候初始化的呢?静态构造函数和静态字段呢?今天 ...
- [C#解惑] #1 在构造函数内调用虚方法
谜题 在C#中,用virtual关键字修饰的方法(属性.事件)称为虚方法(属性.事件),表示该方法可以由派生类重写(override).虚方法是.NET中的重要概念,可以说在某种程度上,虚方法使得多态 ...
- Python 包管理工具解惑
Python 包管理工具解惑 本文链接:http://zengrong.net/post/2169.htm python packaging 一.困惑 作为一个 Python 初学者,我在包管理上感到 ...
- 《浅谈磁盘控制器驱动》,磁盘控制器驱动答疑解惑![2012.1.29完结]by skyfree
<浅谈磁盘控制器驱动>,磁盘控制器驱动答疑解惑![2012.1.29完结] https://www.itiankong.net/thread-178655-1-1.html Skyfre ...
随机推荐
- c++11多线程---线程锁(mutex)
#include<mutex> 包含四类锁: 1 std::mutex 最基本也是最常用的互斥类 2 std::recursive_mutex 同一线程内可递归 ...
- 全面解读php-引用变量(&)
本文讲述引用传值的核心原理,看完即可扫清一切和引用传值相关的内容,不会了记得画图. 一.memory_get_usage的使用 传值赋值 // 定义一个变量 $a = range(0, 10000); ...
- Go语言程序结构
注意:Go语言源码文件编码格式必须是 UTF-8 格式,否则会导致编译器出错. 1.语言变量 a) 指定变量类型,声明后若不赋值,使用默认值. var name string b) 根据值自行判定变量 ...
- Java编写时钟 Applet 程序
简单分析: package clockApplet; import java.applet.Applet; import java.awt.Color; import java.awt.Graphic ...
- 十:jinja2模板查找路径
jinja2用于渲染模板 查找路径 1.默认从项目根目录下的templates下面找指定的html文件 也可以往下新建路径 2.指定自定义路径 在Flask的源码中,指定了默认路径为templates ...
- No module named 'pip'
https://blog.csdn.net/wuyepiaoxue789/article/details/84033651 可以首先执行 python -m ensurepip 然后执行 pyth ...
- 重叠IO 模型
1. 重叠模型的优点 2. 重叠模型的基本原理 3. 关于重叠模型的基础知识 4. 重叠模型的实现步骤 5. 多客户端情况的注意事项 一.重叠模型的优点 1.可以运行在支持Winsock2的所有W ...
- React Native调用系统浏览器
import { Linking} from 'react-native'; //使用系统浏览器访问指定URLexport const contactBaidu = () => { var ba ...
- c++ 指针(三)
指针 (6)传递指针给函数 只需要简单地声明函数参数为指针类型即可 #include <iostream> #include <ctime> using namespace s ...
- 【HANA系列】SAP ECLIPSE中创建ABAP项目失败原因解析
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP ECLIPSE中创建AB ...