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 ...
随机推荐
- 让socket端口不被子进程继承
有两个程序A,B A绑定端口8000,然后用system函数启动程序B,然后再把A杀掉,这个时候再重启A的时候会发现绑定端口失败, 原因是端口被B绑定了,实际上是被继承了,为了避免这种情况,需要对主s ...
- 转自B站 真希望我在20岁就懂得的10个人生道理 主讲:王魄
视频地址:https://www.bilibili.com/video/av65194244?from=search&seid=15261178568916939794 这位阿姨讲得还行,特别 ...
- PDS常用快捷键
绿色在Layout和Router中共用 1.PDS常用快捷键:2019-07-28 17:06:07 快捷键 说明 备注 shiftt + 左键双击 布线状态下,进行过孔放置 ctrl + 左键双 ...
- python自然语言处理学习笔记1
1.搭建环境 下载anaconda并安装,(其自带python2.7和一些常用包,NumPy,Matplotlib),第一次启动使用spyder 2.下载nltk import nltk nltk.d ...
- freetype HarfBuzz fontconfig Cairo 编译顺序
There is also a circular dependency between freetype and HarfBuzz. Note that fontconfig and Cario ar ...
- WebSocket-Node
WebSocket Client & Server Implementation for Node 参考资料:[https://github.com/theturtle32/WebSocket ...
- C#学习笔记三(委托·lambda表达式和事件,字符串和正则表达式,集合,特殊的集合)
委托和事件的区别 序号 区别 委托 事件 1 是否可以使用=来赋值 是 否 2 是否可以在类外部进行调用 是 否 3 是否是一个类型 是 否,事件修饰的是一个对象 public delegate vo ...
- 【HTTP】三、HTTP状态保持机制(Cookie和Session)
前面我们提到HTTP协议的特点:无连接.无状态.无连接带来的时间开销随着HTTP/1.1引入了持久连接的机制得到了解决.现在来关注其"无状态"的特点. 所谓的无状态,就是指 ...
- 《Python编程从0到1》笔记1——表达式的风格(前缀、中缀、后缀)
运算符和运算数组成表达式.运算符和运算数的出现次序会影响表达式乃至程序设计语言的风格. 1.前缀表达式 前缀,是指运算符的位置在前.前缀风格的一个例子是函数调用,如求最大值函数:max(3, 2, 5 ...
- 【VS开发】浅谈UDP(数据包长度,收包能力,丢包及进程结构选择)
UDP数据包长度 UDP数据包的理论长度 udp数据包的理论长度是多少,合适的udp数据包应该是多少呢?从TCP-IP详解卷一第11章的udp数据包的包头可以看出,udp的最大包长度是2^16-1的个 ...