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 ...
随机推荐
- 12个Sublime Text应用技巧[转载]
本文为您提供Sublime Text编辑器的12个技巧和诀窍,深入挖掘这个看似简洁的代码编辑器,背后所隐藏的实现各种高级功能的无限可能. 1) 选择 以下是一些Sublime Text选择文本的快捷键 ...
- golang 开源项目: 配置解析模块--config
在golang中,配置文件经常使用json格式.json格式的语法,有些繁琐,尤其是出现嵌套的时候,每一块都需要大括号包裹,看起来很臃肿. 本着简单易用的原则,个人开发了一个配置解析模块config, ...
- 为解决Thymeleaf数字格式化问题而想到的几种方案
背景: spring后端输出double类型数据,前端使用thymeleaf框架,格式化double数据类型,由于需要显示原值(比如原来录入5,而不能显示5.00),因此需要存储数值(存储值为deci ...
- Android 动态申请权限
AndroidManifest.xml(清单文件)添加需要的权限 <uses-permission android:name="android.permission.ACCESS_CO ...
- PyCharm安装+破解
PyCharm 是一款功能强大的 Python 编辑器,具有跨平台性,鉴于目前最新版 PyCharm 使用教程较少,为了节约时间,来介绍一下 PyCharm 在 Windows下是如何安装的. 这是 ...
- tomcat gc和内存
tomcat启动参数,将JVM GC信息写入tomcat_gc.log CATALINA_OPTS='-Xms512m -Xmx4096m -XX:PermSize=64M -XX:MaxNewSiz ...
- 如何实现在Eclipse导入MySQL驱动包
1 右键项目->Properties->Java Build Path->Libraries->Add External JARs...->mysql-connector ...
- Java基础之Volatile原理
原文链接: http://www.aoaoyi.com/archives/956.html 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据 的读取和写入.由于程序运 ...
- tarjan缩点相关知识及代码
emmm原谅我确实是找不到不用缩点的tarjan题才会想到自学一下缩点这个东西的.. 题目没有,只能自己出数据并手动模拟... 首先看一张图(懒得画,还是看输入数据吧,劳烦自行画图..) 7 9(n个 ...
- JsonProperty 使用
引入 依赖 <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId> ...