libhv之hloop_process_ios源码分析

news2024/9/24 3:27:02

上一篇文章对hloop源码大概逻辑和思想进行了一个简单的分析,其中主要涉及三类(timer>io>idles)事件处理。下面将对hloop_process_ios事件做一下简单的分析。

int hloop_process_ios(hloop_t* loop, int timeout) {
    // That is to call IO multiplexing function such as select, poll, epoll, etc.
    //iowatcher_poll_events主要针对不同模型下的IO事件处理,代码将根据环境选择其一
    int nevents = iowatcher_poll_events(loop, timeout);
    if (nevents < 0) {
        hlogd("poll_events error=%d", -nevents);
    }
    return nevents < 0 ? 0 : nevents;
}

在这里插入图片描述
下面将以epoll模型为例,对IO进行一个简单的分析。

iowatcher_poll_events总结

  1. epoll_wait检测io事件,如果存在则加入pendding队列,如果不存在则直接返回
int iowatcher_poll_events(hloop_t* loop, int timeout) {
    epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
    if (epoll_ctx == NULL)  return 0;
    if (epoll_ctx->events.size == 0) return 0;
    //等待io事件,如果存在事件则加入pendding队列,单线程模型
    int nepoll = epoll_wait(epoll_ctx->epfd, epoll_ctx->events.ptr, epoll_ctx->events.size, timeout);
    if (nepoll < 0) {
        if (errno == EINTR) {
            return 0;
        }
        perror("epoll");
        return nepoll;
    }
    if (nepoll == 0) return 0;
    int nevents = 0;
    for (int i = 0; i < epoll_ctx->events.size; ++i) {
        struct epoll_event* ee = epoll_ctx->events.ptr + i;
        int fd = ee->data.fd;
        uint32_t revents = ee->events;
        if (revents) {
            ++nevents;
            hio_t* io = loop->ios.ptr[fd];
            if (io) {
                if (revents & (EPOLLIN | EPOLLHUP | EPOLLERR)) {
                    io->revents |= HV_READ;
                }
                if (revents & (EPOLLOUT | EPOLLHUP | EPOLLERR)) {
                    io->revents |= HV_WRITE;
                }
                //加入pendding队列
                EVENT_PENDING(io);
            }
        }
        if (nevents == nepoll) break;
    }
    return nevents;
}

此时看看epoll.c源码接口

int iowatcher_init(hloop_t* loop);
int iowatcher_cleanup(hloop_t* loop);
int iowatcher_add_event(hloop_t* loop, int fd, int events);
int iowatcher_del_event(hloop_t* loop, int fd, int events);
int iowatcher_poll_events(hloop_t* loop, int timeout);

发现模型接口很简单也很统一:初始化模型,加入事件,检测事件,删除事件,清理模型

1. io模型何时与loop绑定的呢?loop初始化即绑定或者在add_event的时候检测绑定
void hloop_init(hloop_t* loop) {
	.....
	 // 初始化iowatcher
    iowatcher_init(loop);
	......
}

int iowatcher_add_event(hloop_t* loop, int fd, int events) {
    if (loop->iowatcher == NULL) {
        iowatcher_init(loop);
    }
    ......
}
2. fd何时与IO模型绑定的呢?io异步读写的时候进行io模型绑定
//read的时候添加io,
int hio_read (hio_t* io) {
    if (io->closed) {
        hloge("hio_read called but fd[%d] already closed!", io->fd);
        return -1;
    }
    hio_add(io, hio_handle_events, HV_READ);
    if (io->readbuf.tail > io->readbuf.head &&
        io->unpack_setting == NULL &&
        io->read_flags == 0) {
        hio_read_remain(io);
    }
    return 0;
}

//将IO和模型绑定iowatcher_add_event
int hio_add(hio_t* io, hio_cb cb, int events) {
    printd("hio_add fd=%d io->events=%d events=%d\n", io->fd, io->events, events);
#ifdef OS_WIN
    // Windows iowatcher not work on stdio
    if (io->fd < 3) return -1;
#endif
    hloop_t* loop = io->loop;
    if (!io->active) {
        EVENT_ADD(loop, io, cb);
        loop->nios++;
    }

    if (!io->ready) {
        hio_ready(io);
    }

    if (cb) {
        io->cb = (hevent_cb)cb;
    }

    if (!(io->events & events)) {
        iowatcher_add_event(loop, io->fd, events);
        io->events |= events;
    }
    return 0;
}

至此io和loop关联完成。

总结

  1. 代码根据编译选项()选则某一种IO模型
  2. loop在初始化的时候将loop和IO模型绑定,默认创建custom event,即socket
  3. 在fd进行读(hio_read )写(hio_write)的时候将fd添加到IO模型
  4. hloop_process_ios 在IO模型检测(epoll_wait)已经准备就绪的IO事件,并且加入pendding队列。

为了更一步了解io细节,下一步将对hio源码进行讲解分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/797266.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vr禁毒毒驾模拟体验从源头拒绝毒品,预防毒品

俗话说&#xff0c;一念天堂&#xff0c;一念地狱。吸毒一口&#xff0c;掉入虎口。吸毒对人体的危害非常大&#xff0c;普通人吸毒会导致家破人亡&#xff0c;明星吸毒会毁掉自己的大好星途。没有感同身受&#xff0c;何来悲喜相通&#xff0c;毒品危害认知VR模拟情景体验是VR…

助力工业物联网,工业大数据之油站事实指标需求分析【十九】

文章目录 01&#xff1a;油站事实指标需求分析02&#xff1a;油站事实指标构建 01&#xff1a;油站事实指标需求分析 目标&#xff1a;掌握DWB层油站事实指标表的需求分析 路径 step1&#xff1a;目标需求step2&#xff1a;数据来源 实施 目标需求&#xff1a;基于油站信息及…

Blend for Visual Sdudio创建C++工程

&#xff08;1&#xff09;打开Blend for Visual Sdudio &#xff08;2&#xff09;点击“创建新项目” &#xff08;3&#xff09;在最右侧下拉到最底部&#xff0c;点击“安装多个工具和功能” &#xff08;4&#xff09;在最底部点击“关闭” &#xff08;5&#xff09;点击…

【电压和电压稳定指数研究】带多台配电发电机 (DG) 的径向配电系统研究【IEEE33节点】(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码实现 &#x1f4a5;1 概述 电压和电压稳定指数研究是关于电力系统中电压水平和其稳定性的研究。电力系统中的电压是指电网中的电压水平&#xff0c;通常以相电压&#xf…

树莓派本地快速搭建web服务器,并发布公网访问

文章目录 树莓派本地快速搭建web服务器&#xff0c;并发布公网访问 树莓派本地快速搭建web服务器&#xff0c;并发布公网访问 随着科技的发展&#xff0c;电子工业也在不断进步&#xff0c;我们身边的电子设备也在朝着小型化和多功能化演进&#xff0c;以往体积庞大的电脑也在…

vue3 - 报错 Cannot use ‘in‘ operator to search for ‘path‘ in undefined (完美解决)

问题描述 在vue3项目中,浏览器控制台报错 Cannot use ‘in’ operator to search for ‘path’ in undefined 详细解决方案。 解决方案 在创建vue3的路由时,报了这样的错:Cannot use ‘in’ operator to search for ‘path’ in undefined,

flutter开发实战-父子Widget组件调用方法

flutter开发实战-父子Widget组件调用方法 在最近开发中遇到了需要父组件调用子组件方法&#xff0c;子组件调用父组件的方法。这里记录一下方案。 一、使用GlobalKey 父组件使用globalKey.currentState调用子组件具体方法&#xff0c;子组件通过方法回调callback方法调用父组…

U盘里的资料丢失怎么恢复,分享两种有效解决方法

平常我们在用u盘拉文件的时候&#xff0c;有时候会突然发现&#xff0c;本来好好的文件就无缘无故丢失了&#xff0c;这是因为什么情况呢&#xff1f;一般来说&#xff0c;出现这种问题&#xff0c;可能是因为u盘文件被格式化&#xff0c;或者u盘存储损坏了。但是呢&#xff0c…

一键式三分钟轻松打造线上展厅

导语&#xff1a; 在数字时代&#xff0c;线上展厅已成为企业展示品牌和产品的重要方式。随着虚拟现实&#xff08;VR&#xff09;技术的发展&#xff0c;蛙色VR平台成为众多企业选择的首选&#xff0c;因其独特的优势和特点&#xff0c;让线上展厅的打造变得轻松、高效且令人…

使用C#基于ComPDFKit SDK快速构建PDF阅读器

在当今世界&#xff0c;Windows 应用程序对我们的工作至关重要。随着处理 PDF 文档的需求不断增加&#xff0c;将 ComPDFKit PDF 查看和编辑功能集成到您的 Windows 应用程序或系统中&#xff0c;可以极大地为您的用户带来美妙的体验。 在本博客中&#xff0c;我们将首先探索集…

JGIT获取远程仓库、本地仓库提交版本号

https://www.freesion.com/article/50181381474/ JGIT获取远程仓库、本地仓库提交版本号 一、环境搭建二、项目结构二、代码部分 GitUtils.javaGitInfoAtom.java三、运行结果&#xff1a;总结 一、环境搭建 Maven依赖导入 <dependency><groupId>org.eclipse.jg…

进入linux系统中修改网段-ip

第一步 &#xff1a;开启虚拟机 cd 到 /etc/sysconfig/network-scripts 目录下&#xff0c;输入命令给ls,展示这个目录下文件和文件夹 第二步&#xff1a;进入到以ifcfg开头的文件 # ifcfg开头的文件&#xff0c;如果有多个网卡&#xff0c;有多个ifcfg-ensxx文件 命令…

【从零开始学爬虫】采集全国各行业经销商网点数据

l 采集网站 【场景描述】采集全国各行业经销商网点数据&#xff0c;以建材行业为例。 【源网站介绍】买购网MAIGOO.COM建材家居频道&#xff0c;专门提供地面材料、墙顶饰材、洁具五金、门窗楼梯、水电电工、外墙材料、照明灯饰、家纺布艺、家具定制等行业&#xff0c;最新品…

LeetCode.189(轮转数组)

对于轮转数组这个题&#xff0c;文章一共提供三种思路&#xff0c;对于每种思路均提供其对应代码的时间、空间复杂度。 目录 1. 创建变量来保存最后一个数&#xff0c;并将其余数组向前挪动一位 &#xff1a; 1.1 原理解析&#xff1a; 1.2 代码实现&#xff1a; 2.创建一个…

【学习笔记】行为识别SOTA方法比较

这里写目录标题 前言方法1 基于CNN的方法Slow-fast&#xff1a; 2 基于Vision-Transformer的方法Video TimeSformer :Video Swin Transformer : 3、基于自监督的方法VideoMAE&#xff1a; 4、基于多模态的方法Intern video: 前言 常用行为识别数据集包括&#xff1a;HMDB-51、…

TL-ER3220G设置vlan

TL-ER3220G是企业宽带路由器。 自带5个RJ45接口。 其中接口1到接口4都可以接入宽带线路。最多可以并接4路。 本例由接口1接入宽带&#xff0c;默认接口2到接口4组成1个vlan&#xff0c;名称vlan。其中接口5特殊&#xff0c;带宽最大100M。 计划将接口2和接口4组成第一个vlan&…

STM32使用HAL库BH1750光照度传感器

开发环境 单片机&#xff1a;STM32F103C8T6 光照度传感器&#xff1a;BH1750 IDE&#xff1a;KEILSTM32CUBEMX 单片机配置 1、STM32CUBEMX BH1750代码 1、头文件 /* ************************************************* BH1750光照数据计算&#xff08;LUX&#xff09; …

H5和小程序测试点分析

最近接触了较多关于H5页面的测试&#xff0c;H5页面的测试除了业务逻辑功能测试外&#xff0c;其他部分的测试方法基本是可以通用的&#xff0c;在此对H5页面和小程序的一些通用测试方法进行总结分享给大家。 H5优势&#xff1a; 1.H5可以跨平台&#xff0c;开发成本相对较低…

中共湖南麒麟信安科技股份有限公司委员会召开庆祝建党102 周年暨“七一”表彰大会

为隆重庆祝中国共产党成立 102 周年&#xff0c;6月30日下午&#xff0c;中共湖南麒麟信安科技股份有限公司委员会召开庆祝建党102 周年暨“七一”表彰大会。麒麟信安党委书记王忠锋出席会议&#xff0c;党委副书记李广辉主持会议&#xff0c;全体党委委员、各支部委员、受表彰…

Gitlab 合并分支与请求合并

合并分支 方式一&#xff1a;图形界面 使用 GitGUI&#xff0c;右键菜单“GitExt Browse” - 菜单“命令” - 合并分支 方式二&#xff1a;命令行 在项目根目录下打开控制台&#xff0c;注意是本地 dev 与远程 master 的合并 // 1.查看本地分支&#xff0c;确认当前分支是否…