Libev源码解析

2023-05-16

最近在看libev源码,算是对libev的源码有个比较清晰的了解。

总共分3部分来介绍libev.

1 Libev是什么

Libev是基于Reactor模式的一个高性能,支持高并发的事件库。它本身不仅支持IO,timer(定时器),还支持signal, fork等。并且它短小精悍 ,并且C语言实现。

2. Libev重要的数据结构

只有了解并且熟悉了Libev的基本数据结构,才能更顺利的理解Libev怎么实现的事件库的。

基类ev_watcher

typedef struct ev_watcher {                                          
  int active; // 激活标志                                            
  int pending; // 等待事件数                                         
  int priority; //优先级                                             
  void* data;                                                        
  // 回调函数                                                        
  void (*cb)(struct ev_loop* loop, struct ev_watcher* w, int revent);
} ev_watcher;                                                       

ev_watcher_list

typedef struct ev_watcher_list {
  int active;
  int pending;
  int priority;
  void* data;
  void (*cb)(struct ev_loop* loop, struct ev_watcher_list* w, int revent);
  struct ev_watcher_list* next;
} ev_watcher_list;

ev_watcher_time
typedef double ev_tstamp;
typedef struct ev_watcher_time {
  int active; // 激活标志
  int pending; // 等待事件数
  int priority; //优先级
  void* data;
  // 回调函数
  void (*cb)(struct ev_loop* loop, struct ev_watcher_time* w, int revent);
  ev_tstamp at;
} ev_watcher_time;
ev_timer
typedef struct ev_timer {
  int active; // 激活标志
  int pending; // 等待事件数
  int priority; //优先级
  void* data;
  // 回调函数
  void (*cb)(struct ev_loop* loop, struct ev_watcher_time* w, int revent);
  ev_tstamp at; // 在"at"之后发生timeout事件
  ev_tstamp repeat; // 在"repeat"之后触发timeout事件,循环
} ev_timer;
ev_io
typedef struct ev_io {
  int active;
  int pending;
  int priority;
  void* data;
  void (*cb)(struct ev_loop *loop, struct ev_io *w,int revents);
  struct ev_watcher_list *next;
  int fd;// 文件描述符
  int events;// 事件類型
} ev_io;
typedef struct ev_signal {
  int active;
  int pending;
  int priority;
  void* data;
  void (*cb)(struct ev_loop *loop, struct ev_signal *w,int revents);
  struct ev_watcher_list *next;
  int signum;  // 信号量like SIGxxx

} ev_signal;
ev_prepare
/* invoked for each run of the mainloop, just before the blocking call */
/* you can still change events in any way you like */
/* revent EV_PREPARE */
typedef struct ev_prepare {
  int active;
  int pending;
  int priority;
  void* data;
  void (*cb)(struct ev_loop *loop, struct ev_prepare *w,int revents);
} ev_prepare;
ev_check
/* invoked for each run of the mainloop, just after the blocking call */
/* revent EV_CHECK */
typedef struct ev_check {
  int active;
  int pending;
  int priority;
  void* data;
  void (*cb)(struct ev_loop *loop, struct ev_check *w,int revents);
} ev_check;
ev_loop:
struct ev_loop {
  ev_tstamp ev_rt_now;
  #define ev_rt_now ((loop)->ev_rt_now)
  #define VAR(name,decl) decl;
  #include "ev_vars.h" // 包含众多成员
  #undef VAR
};
ev_loop的成员:
ev_tstamp now_floor; /* last time we refreshed rt_time */ 
ev_tstamp mn_now; // 当前单调时间,系统开机时间 
ev_tstamp rtmn_diff; // difference realtime - monotonic time 
unsigned int origflags;
int backend; //epoll 、 kqueue 、 poll 、 select 、 port 标记
int activecnt;// 激活事件总数
int backend_fd;// 对于 epoll, 为 epoll_create 返回的描述符 
int * fdchanges;// 事件队列
int fdchangemax;// 当前最大事件数 
int fdchangecnt;// 事件数
ANPENDING *pendings [NUMPRI];// 待处理队列
int pendingmax [NUMPRI];// 当前最大等待事件的数量 
int pendingcnt [NUMPRI];// 记录每个优先级的数量

ANFD:

typedef struct{
  ev_watcher_list* head; //监听者链表
  unsigned char events; //监听的事件
  unsigned char reify;//状态位 用来表示具体是EV_ANFD_REIFY还是EV_IOFDSET
  unsigned char emask;//epoll用来保存内核mask的值
  unsigned char unused;//同名字
#if EV_USE_EPOLL
  unsigned int egen;//
#endif
#if EV_SELECT_ISWINSOCKET || EV_USE_IOCP
  SOCKET handle;//
#endif
#if EV_USE_IOCP
  OVERLAPPED or,ow;//
#endif
} ANFD;
ANPENDING
typedef struct {
  ev_watcher* w;
  int events;
} ANPENDING;
堆结构的节点(用于管理定时器)
typedef struct {
  ev_tstamp at;
  ev_watcher_time* w;
} ANHE;
开始前准备:

ev_init(ev_TYPE *watcher, callback

ev_set_priority(ev_TYPE*watcher, int priority)设置优先级

ev_io_init(ev_io *, callback, int fd, int events)

Fd:  EV_READ, EV_WRITEor EV_READ | EV_WRITE

ev_io_set(ev_io *, int fd, int events)

ev_timer_init(ev_timer *, callback, ev_tstamp after, ev_tstamp repeat)

ev_timer_set(ev_timer *, ev_tstamp after, ev_tstamp repeat)


3. ev_run执行流程

下图为ev_run的具体流程
backend_poll(epoll_poll)过程,是通过epoll_wait讲IO事件放入pendings数组里。下图为backend_poll的具体过程:
epoll_poll之后,将事件从anfds中找到对应的ANFD。
anfds, fdchanges和fd的关系如下图:
然后再取ANFD中的watcher,最后将watcher和发生的事件赋值给结构体ANPENDING,最后将ANPENDING按照优先级放入二维数组pendings中。
fd,andfs,pendings之间的关系如下:
上图表示,通过backend_poll函数中调用fd_event/fd_event_nocheck将epoll_wait之后拿到就绪fd,在用fd作为下标的anfds中查询,得到ANFD,之后通过ev_feed_event函数将watcher,event组成结构体ANPENDING,插入到pendings数组中。

通过epoll_poll之后,已经将就绪的IO事件放入pendings数组中,随后需要放入的是最小堆中的超时watcher。超时watcher放入过程如下:


在处理最小堆的watcher时,会先讲watcher放入rfeeds数组中,随后再逆序从rfeed中事件放入pendings数组中。这两个数组的关系如下:


在收集完所有的watcher之后,进入EV_INVOKE_PENDING的流程中,也就是从pendings数组中按照优先级顺序从数组中逆序去除watcher进行invoke_cb的回调。

具体过程如下:


其中pending数组和EV_INVOKE_PEINDING的过程关系图如下:



4  参考文献:

http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.podlibev官方文档)
http://blog.chinaunix.net/uid-8048969-id-5008922.html(事件库libev)



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Libev源码解析 的相关文章

  • Spring源码解析3-beanFactoryPostProcessor的执行

    refresh 中的invokeBeanFactoryPostProcessors beanFactory invokeBeanFactoryPostProcessors xff0c 实例化并且调用所有已经注册了的beanFactoryPo
  • 深入学习 esp8266 wifimanager源码解析(打造专属自己的web配网)(最全的wifimanager介绍))

    原文地址 xff1a https my oschina net u 4269090 blog 3329239 1 前言 废话少说 xff0c 本篇博文的目的就是深入学习 WifiManager 这个github上非常火爆的ESP8266 w
  • 【Zipkin】zipkin-dependencies计算 - 源码解析

    zipkin dependencies离线计算拓扑图依赖 本文分析mysql存储 xff08 后续准备接入Doris直接计算依赖关系 xff0c 所以分析不关注存储 xff09 查找main方法 ZipkinDependenciesJob
  • Guava-Collections2源码解析

    构造器 private Collections2 私有构造器 xff0c 也没有静态构造器 xff0c 所以可以很明确它是一个纯工具类了 功能方法 filter过滤方法 传入一个带过滤的容器 xff0c 和一个实现过滤规则的函数类 xff0
  • GVINS源码解析

    GVINS是基于VINS MONO写的 xff0c 视觉 IMU部分与VINS MONO类似 xff0c 可参考我的前一篇文章VINS MONO学习 这篇文章主要解析与GNSS有关的部分 持续更新中 文章目录 estimator node
  • DataBinding源码解析

    DataBinding是Google发布的支持库 xff0c 它可以实现UI组件及数据源的双向绑定 使用DataBinding可以轻松实现MVVM模式 xff0c 当数据发生变化时会体现在View界面上 xff0c 反过来界面内容变化也会同
  • Volley源码解析

    概述 本文基于Volley 1 1 1版本的源码 Volley是Google官方出的一套小而巧的异步请求库 xff0c 该框架封装的扩展性很强 xff0c 支持HttpClient HttpUrlConnection xff0c 甚至支持O
  • Android-Handler源码解析-Message

    成员变量 标识Message public int what 存储简单数据 xff0c 如果存储复杂的数据使用setData 方法 public int arg1 public int arg2 发送给接收者的任意对象 public Obj
  • OutLine源码解析 -- 为什么要尽量避免使用OutLine

    相信很多人在刚入职Unity的时候都被告诫过尽量避免使用OutLine xff0c 只知道它很费性能 xff0c 但是很多人并不知道它为什么很费性能 今天通过源码来探索一下 首先看一下OutLine cs里的源码 public overri
  • Redux源码解析(部分)

    相信用过React的小伙伴对于Redux一定不陌生 xff0c A Predictable State Container for JS Apps xff0c 这是官方文档对于Redux的定义 xff0c 即一款适用于JS Apps的可预测
  • yolov5源码解析--损失计算与anchor

    本文章基于yolov5 6 2版本 主要讲解的是yolov5在训练过程中是怎么由推理结果和标签来进行损失计算的 损失函数往往可以作为调优的一个切入点 xff0c 所以我们首先要了解它 一 代码入口 损失函数的调用点如下 xff0c 在tra
  • MSCKF 源码解析 一

    论文 xff1a https arxiv org abs 1712 00036 源码路径 https github com daniilidis group msckf mono 源码框架 上图展示了整个msckf源码框架 xff0c 每当
  • java源码解析JavaParser

    package com bootdo jparser import java io File import java io FileNotFoundException import com github javaparser JavaPar
  • pomelo源码解析--新建项目(cli工具: pomelo)

    pomelo怎么新建项目 官方文档 1 安装pomelo 2 新建项目HelloWorld 我简单整理了下创建新项目关键步骤 xff1a 安装pomelo 方式一 xff1a npm install pomelo g 方式二 xff1a g
  • Pytorch学习(3) —— nn.Parameter nn.ParameterList nn.ParameterDict 源码解析

    为了更好理解Pytorch基本类的实现方法 xff0c 我这里给出了关于参数方面的3个类的源码详解 此部分可以更好的了解实现逻辑结构 xff0c 有助于后续代码理解 xff0c 学pytorch的话这个不是必须掌握的 xff0c 看不懂也没
  • libev学习系列之二:libev下载

    libev学习系列之二 libev下载 版本说明 版本 作者 日期 备注 0 1 ZY 2019 5 31 初稿 目录 文章目录 libev学习系列之二 libev下载 版本说明 目录 官网 GitHub 我的某度网盘 官网 可以去官网下载
  • LevelDB源码解析(2) SkipList(跳跃表)

    你也可以通过我的独立博客 www huliujia com 获取本篇文章 背景 SkipList是LevelDB的MemTable使用的底层存储结构 LevelDB实现了一个支持泛型的跳跃表 本文不会具体介绍跳跃表的数据结构 如果读者不了解
  • libev学习系列之三:libev编译安装

    libev学习系列之三 libev编译安装 版本说明 版本 作者 日期 备注 0 1 ZY 2019 5 31 初稿 目录 文章目录 libev学习系列之三 libev编译安装 版本说明 目录 源码结构 正常编译 交叉编译 源码结构 4 2
  • 对象池(连接池):commons-pool2源码解析:GenericObjectPool的继承结构、构造方法

    概述 GenericObjectPool是apache commons pool 源码分析基于commons pool2 框架中的一个非常重要的类 解析GenericObjectPool就有必要先了解一下apache commons poo
  • Android 相机库CameraView源码解析 (三) : 滤镜相关类说明

    1 前言 这段时间 在使用 natario1 CameraView 来实现带滤镜的 预览 拍照 录像 功能 由于 CameraView 封装的比较到位 在项目前期 的确为我们节省了不少时间 但随着项目持续深入 对于 CameraView 的

随机推荐

  • Qt安装显示:MSVC2015 编译器带有感叹号,及解决办法

    在Qt安装完成后 xff0c 选项 KIt界面显示 xff1a MSVC2015 的两个编译器的图标会变为带有感叹号的一个黄色图标 xff0c 如下图所示 xff1a 图 1 Kits 显示的界面上 MSVC2015 的两个编译器的图标会变
  • VR中的交互方式 好

    http www gameres com 495107 html
  • Mac常用应用 brew list

    61 61 gt Formulae ca certificates gdbm go libidn2 mpdecimal python 64 3 10 readline wget delve gettext jsonschema libuni
  • Slack 消息回传

    Slack预留了回传接口 可以将报错 告警信息等回传到Slack频道里 https api slack com messaging webhooks
  • Postgres 最大连接数满了: remaining connection slots are reserved for non-replication superuser connections

    最近遇到链接pg数据库报错 xff1a remaining connection slots are reserved for non replication superuser connections 百度说 xff0c 是由于设置的最大
  • oracle游标:fetch和for循环游标

    1 fetch 显式的open close Declare Cursor cur Is Select xtwldm From xtm14 curRow cur Rowtype Begin Open Cur Loop Fetch cur In
  • .net {"已添加项。字典中的关键字:“**”所添加的关键字:“**”"}

    用户代码未处理 System ArgumentException HResult 61 2147024809 Message 61 已添加项 字典中的关键字 00 所添加的关键字 00 Source 61 mscorlib StackTra
  • docker: 为运行的container增加多个端口

    1 list all docker process and stop running container test01 docker ps a docker stop test01 2 commit the container docker
  • git prune, git remote prune, git fetch --prune 三者异同

    远程分支的3种状态 远程仓库确实存在分支dev本地版本库 xff08 git xff09 中的远程快照和远程分支建立联系的本地分支 git prune https git scm com docs git prune Prune all u
  • Jmeter_Non HTTP response code: java.net.SocketException

    error msg rc 61 span class hljs string 34 Non HTTP response code java net SocketException 34 span rm 61 span class hljs
  • SQL Server 数据库导入导出数据

    Data Micration between SQL Server Database 1 减少源数据库的导出数据 排除日志表数据 xff1a 日志表数据体积大且没有导出价值 精简掉备份表 xff1a 为了保证数据的安全 xff0c 一般会对
  • 程序员读书啦!!!

    成为Java顶尖程序员 xff0c 看这11本书就够了 xff1a http blog csdn net u012410733 article details 51869105 编程科普书籍推荐 xff1a http blog csdn n
  • Windows设置本地DNS域名解析Hosts

    DNS Domain Name System 域名系统 xff1a 为了加快定位IP地址的速度 将域名映射进行层层缓存的系统 目的 xff1a 互联网通过IP xff08 10 223 146 45 xff09 定位浏览器建立连接 xff0
  • 机器学习之缺失样本重采样策略

    1 引言 在机器学习领域中 对不均衡数据集进行建模是我们训练模型时经常遇到的挑战 比如在分类问题上 训练集上类别的平衡对模型建模起着重要作用 如果直接对类间不平衡的数据进行建模 xff0c 即数据集中存在少数类 xff0c 这样训练好的模型
  • aptitude与apt-get

    aptitude 与 apt get 一样 xff0c 是 Debian 及其衍生系统中功能极其强大的包管理工具 与 apt get 不同的是 xff0c aptitude 在处理依赖问题上更佳一些 举例来说 xff0c aptitude
  • js 冒泡排序、函数(function)

    一 冒泡排序 原理 数组中的元素两个两个进行比较 xff0c 如果前面的数大于后面的数就进行交换 xff0c 如果前面的数小于后面的数不交换位置 xff0c 后面的继续和下一个进行比较 整体代码 xff1a 冒泡排序 var arr 10
  • python 中Dict 转 Json

    最近在公司需要写个小工具 xff0c 运用到的python xff0c 然后需要将Dict转成Json 之前遇到转换Json失败 xff0c 然后以为复杂的Entity结构 xff0c 不能用Json的库Json dump xff0c 进行
  • Zabbix监控

    由于本人工作职责的一部分 xff0c 需要用Zabbix监控 xff0c 所以在此贴一下Zabbix监控 实在觉得Zabbix监控做的太牛掰 xff0c 先打Tag xff0c 周末再来补全
  • 看完23岁的我在干嘛之后有感

    现在我已经25岁了 xff0c 先说我23岁的时候吧 xff0c 23岁我在干嘛 xff0c 刚上研究生 xff0c 好像貌似一切都挺顺的 xff0c 考研成功 xff0c 进入北京比较好的一所大学读计算机 xff1b 然后是和前任分手 x
  • Libev源码解析

    最近在看libev源码 xff0c 算是对libev的源码有个比较清晰的了解 总共分3部分来介绍libev 1 Libev是什么 Libev是基于Reactor模式的一个高性能 xff0c 支持高并发的事件库 它本身不仅支持IO xff0c