当前位置: 首页 > news >正文

【Linux】高级IO

目录

IO的本质

五种IO模型

非阻塞IO

fcntl

多路转接IO

select

参数介绍

代码示例

select缺点

poll

参数介绍

代码示例

epoll

优点

接口

原理

代码

epoll工作模式

LT与ET

基于epoll的ET模式的Reactor

Reactor项目


IO的本质


五种IO模型

 张三一直盯着鱼鳔,直到有鱼咬钩

李四每间隔一段时间看一次鱼鳔,其它时间在刷手机

王五的鱼竿有铃铛,鱼咬钩会响铃,其它时间在刷手机

赵六有10根鱼竿,轮询检测鱼鳔

田七是老板,他让秘书帮他钓,钓满一桶后通知老板


非阻塞IO

fcntl

这个接口的作用是对文件描述符进行操作

我们如何通过fcntl把某一个文件描述符对应的flag设置成非阻塞?

先用fcntl的getfl获得该文件描述符的flag,再用fcntl的setfl把获得的flag进行设置

返回值为-1,错误码为11(EWOULDBLOCK)表面不是真的出错而是底层没就绪


多路转接IO

select

参数介绍

返回值:大于0表示有返回值个fd就绪,等于0表示超时,没错误但也没就绪,小于0表示出错

第一个参数是要等的文件描述符中最大的文件描述符加1,比如要等1,2,3,那么第一个参数就是3+1

第二,三,四个参数

如果你想关心某一个fd的读事件,那么就在第二个参数位图里面对应位置置1,如果关心写事件就在第三个参数里,第四个参数是异常事件,可关心多个事件

这些位图参数也是输入输出参数,用户给位图置1然后告诉操作系统置1的地方你要关心,操作系统也返回一个位图,告诉用户里面置1的地方已经就绪了

fd位图操作接口

FD_CLR:置0指定fd

FD_ISSET:判断指定fd是否为1

FD_SET:置1指定fd

FD_ZERO:全部置0

第五个参数是一个结构体,负责select的等待时间

还是输入输出参数,比如我设了等待5秒,但是2秒就就绪了,那么会返回5-2秒

代码示例

select监视fd

accept本质需要等待新连接到来,可以看作等待读事件就绪,等的过程就可以交给select

等待时间需要重复设置,因为是输入输出参数导致会保留上一次的剩余时间

等待时间设为nullptr表明一直阻塞等待

处理就绪fd

连接事件就绪,可以直接获取连接了,这样accept不会阻塞直接获取连接

通过辅助数组实现fd的传递,交给select管理

通过遍历辅助数组把对应fd集位置置1,并获得最大fd值

把新的fd加入辅助数组中

完整代码

advance_io_lesson/select · lyh/linux - 码云 - 开源中国


select缺点


poll

参数介绍

poll相当于是select的优化版, poll解决了select的fd有上限的问题,解决了不用每次都维护fd位图集的问题

poll和select共同点:都需要遍历“维护fd”的辅助数组,在内核中遍历检测哪些fd就绪,在用户层遍历检测哪些事件就绪

第一个参数是结构体数组

结构体表示在该fd下,events表示用户要内核关心的事件,revents表示内核告诉用户哪些事件就绪了

short有16个比特位,最多可以表示16种事件

第二个参数表示数组的大小,也就是要关心的fd的个数

第三个参数是等待事件,单位是毫秒


代码示例

内核告诉用户的事件就绪是内核自动写的,用户不用操作了(revents)

poll的代码和select不同点:

成员变量由原本的fd辅助数组改为pollfd结构体数组

构造函数对数组的初始化变了

接口由select改为poll

判断事件就绪改变了,原本用户和内核共用一个位图集交流,现在在结构体里面分开维护了

插入新fd的时候要改为插入整个结构体

完整代码

advance_io_lesson/poll · lyh/linux - 码云 - 开源中国


epoll

优点

epoll是poll的加强版,但是epoll和poll的代码没有相似度,不像poll和select

用户只需要关心就绪队列是否为空,空就是无就绪,非空就是有就绪,再遍历就绪队列把就绪结点一个一个插入到自己维护的结构体数组中


接口

创建一个epoll模型

epoll模型也被当成文件接入了文件模块并且有自己的fd

参数已废弃,大于0就行,返回值是一个fd

获取就绪队列

第一个参数填epoll_create的返回值

第二个参数输出型,是一个结构体数组,会把就绪队列的结构体依次插入数组中

事件

第三个参数是数组最大个数

第四个参数是等待时间,单位是毫秒

返回值

操作红黑树

第一个参数填epoll_create的返回值

第二个参数是选项,增加,修改,删除

第三个参数,要操作哪一个fd

第四个参数,要操作该fd的哪些事件


原理

网卡硬件(物理层)有数据并且就绪了会发生硬件中断,告诉网卡驱动(数据链路层)把数据拿上去,网卡驱动数据就绪了就会调用回调函数,回调函数的作用:向上交付数据给tcp的接收缓冲区(接收队列),查找红黑树查找与这些数据关联的fd以及对应关心事件是否符合,符合就构建就绪结构体插入到就绪队列中

操作系统维护了一颗红黑树,树的结点是结构体,结构体里面有fd和关心事件

操作系统维护了一条就绪队列,当有事件就绪,操作系统就会构造一个结构体连入就绪队列中,这个结构体包含fd和就绪事件

epoll模型


代码

advance_io_lesson/Epoll_Server · lyh/linux - 码云 - 开源中国


epoll工作模式

LT与ET

ET就是每当有新事件来就提醒一次,LT有事件就一直提醒处理

为什么ET都要非阻塞?

因为ET必须一次把数据全部取走,势必会读到空,这时默认是阻塞

ETLT效率取决代码实现

一次取走全部数据,剩余空间就更大

ET与LT本质是一个只在就绪队列添加一次,一个是每次都添加


基于epoll的ET模式的Reactor

Reactor理论

Reactor反应堆是这个游戏面板,每一个洞就是连接对象,下锤子就是调用处理方法

同步体现在select/poll/epoll上,它们要参与等的过程(IO=等+拷贝)

Reactor项目

advance_io_lesson/Reactor · lyh/linux - 码云 - 开源中国

相关文章:

  • 网站建设和优化的好处关键路径
  • 加强网站备案管理专项行动seo公司系统
  • 社区网站制作app拉新推广平台有哪些
  • 网站的设计过程建站工具
  • 小程序推广网站无锡百度快速优化排名
  • 国家城乡住房和建设部网站最新军事报道
  • MySQL:深入总结锁机制
  • 机器学习×第十四卷:集成学习中篇——她从每次错误中修正自己
  • Java实现简易即时通讯系统
  • Linux离线搭建Jenkins
  • C++【生存游戏】开发:荒岛往事 第一期
  • GLib库介绍与linux下应用
  • 基于元学习的回归预测模型如何设计?
  • ubuntu20.04安装多版本python时,如何使用sudo python3.10
  • Linux系统---Nginx配置nginx状态统计
  • 如何使用MQTTX软件来进行MQTT协议的测试
  • Harmony状态管理 @Local和@Param
  • 计算机网络期末复习
  • Git 3天2K星标: Happy-LLM 项目介绍(附教程)
  • 【基础篇-消息队列】—— 如何实现单个队列的并行消费及如何保证消息的严格顺序
  • LangChain网页自动化PlayWrightBrowserToolkit
  • 在Ubuntu下建设自己的本地大模型docker+ollama+openwenui
  • leetcode173.二叉搜索树迭代器
  • 深入理解 BOM:浏览器对象模型详解
  • RabbitMQ是什么?以及优缺点
  • Kafka 监控与调优实战指南(一)