I/O模型

news2025/7/24 5:57:17

网络IO的本质

网络IO的本质就是socket流的读取,通常一次IO读取会涉及两个阶段与两个对象,其中两个对象为:用户进程(线程)Process(Thread)、内核对象(kernel),两个阶段为:等待流数据准备阶段、从内核向进程复制数据阶段。

对于socket而言,第一步通常等待网络上的数据分组到达,然后被复制到内核的某个缓冲区,第二步数据从内核的缓冲区复制到应用进程的缓冲区。

网络IO模型

I/O模型可细分为五种类型:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO、异步IO。

阻塞IO模型

首先,在linux系统中默认所有的IO都是阻塞IO。

阻塞IO的特点是从kernel读取数据时信号并未立刻返回,而是等待数据到达完毕或发生错误才会返回结果,这个过程是阻塞的。

术语描述:当用户进程调用recvfrom这个系统调用时,kernel就开始等待数据到来,而进程这边会处于阻塞状态。当kernel将数据准备好后,就会将数据拷贝到用户进程的缓冲区,然后kernel返回结果,用户进程才会解除block状态,重新运行起来。

非阻塞IO模型

与阻塞IO不同,当用户进程发出recvfrom调用时,如果kernel中数据还没有准备好,那么并不会block用户进程,而是会返回error错误。相对于用户进程而言,每次发送读取操作后,并不需要等待,而是会立刻返回结果,当收到error时,就知道数据未准备完毕,然后继续发送读取操作,直到可以直接读取数据到缓冲区为止。虽然在执行read请求操作时,用户进程并未阻塞,但是当recvfrom将数据从内核拷贝到进程时,用户进程处于阻塞状态。

多路复用IO模型

产生原因

在具有大量IO请求的场景下,需要应用进程创建多个线程去读取数据,每个线程都会调用recvfrom去读取数据。在这种高并发的情况下,可能进程需要创建成千上万个线程,增加服务器负荷,并且造成了严重的资源浪费。

因此,有了多路复用IO模型,使用一个线程去监听多个网络请求,即文件描述符,这样就实现了使用少量线程对大量请求进行监听,然后再让对应的线程进行数据读取。那么目前常用select、poll、epoll函数对fd文件描述符进行监听。

多路复用IO又称事件驱动IO,进程使用IO多路复用在两个阶段都是阻塞的状态,进程使用select函数,其中select函数有一个参数是文件描述符集合,对这些文件描述符进行监听,当文件描述符就绪时,会返回readable信号,然后用户进程调用recvfrom进行读取数据,由于可同时监听多个IO,效率比阻塞IO高。

select

进程调用select后会被阻塞,将需要监听的文件描述符放入fd_set,并将fd_set复制到内核空间,内核空间会对fd_set进行轮询遍历,若无mark值,则会暂时挂起等待超时时间之后继续轮询,直到有数据准备就绪。最后将fd_set复制回用户进程,进行读/写操作。

复杂度O(n)

select的缺点:

1.select监控数量受限

select能监控的fd数量有上限,32位系统一般为1024,64位系统为2048,这个上限可以通过修改参数提高,但是相应的会损失性能。

2.轮询效率低

对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。

3.频繁拷贝复杂,开销大

需要维护一个用来存放大量fd的数据结构,用户空间需要维护一个fd_set,fd_set的每一位都表示一个文件描述符,开始时会将其发给内核,这会使得用户空间和内核空间在传递该结构时复制开销大。

4.select是水平触发

应用程序如果没有完成对一个已经就绪的文件描述符进行IO操作。那么之后select调用还是会将这些文件描述符返回,通知进程。

poll

poll和select基本是一样的,但是它对fd集合做了优化,使用链表存储,解决了连接数上限的问题。

epoll

epoll的实现与上述两种方式完全不同,因此不会造成上述的问题。

同select、poll不同,复杂度O(1),通过三个函数实现流程:

1.epoll_create: 创建一个epoll文件描述符集合,同时底层创建一个红黑树和就绪链表,红黑树存储所监控的文件描述符的节点数据,就绪链表存储就绪的文件描述符的节点数据。

2.epoll_ctl: 用于添加新的描述符,首先判断红黑树中是否存在,如果不存在,插入数据,并告知内核注册回调函数(当文件描述就绪时通过网卡驱动触发),数据就绪后将事件添加到就绪队列中。

3.epoll_wait: 检查链表,并将数据拷贝到用户空间(两者维护的是片共享内存),最后清空链表。其中epoll的工作方式分为LT、ET。

注意:epoll是线程安全的,但是当一个线程调用epollwait,而另一个线程用epollctl向同一个epoll_fd添加一个监测fd后,epollwait有可能被改fd的读/写事件唤醒。

信号驱动IO模型

首先应用进程通过sigaction系统调用安装一个信号处理函数(在内核位置),该系统调用立即返回,进程继续工作(未被阻塞)。当数据准备就绪时,kernel就会为该进程产生一个SIGIO信号,随后用户进程就可以使用recvfrom调用去读取数据到内存,并返回成功指示。

异步IO模型

真正意义上的非阻塞IO,当用户进程发出aio_read操作之后,就立刻可以去做其它的事。另一方面,当kernel的角度,当kernel收到read信号后,会立刻返回结果,所以不会对用户进程block。之后,kernel会等待数据准备完毕,然后将数据拷贝到内存中,完成之后,kernel会给用户进程发送signal信号,表示数据已经read操作完毕。整个过程无阻塞状态的发生。

总结

1.阻塞IO、多路复用IO是两个阶段都处于阻塞状态,非阻塞IO、信号驱动IO是在第二阶段从kernel读取数据时处于阻塞状态,异步IO整个过程都未处于阻塞状态。

2.按照阻塞程度排序:阻塞IO > 非阻塞IO > 多路复用IO > 信号驱动IO > 异步IO ,并且效率由低到高。

3.异步与同步的区别:

在IO模型里面如果请求方从发起请求到数据最后完成的这一段过程中都需要自己参与,那么这种我们称为同步请求;反之,如果应用发送完指令后就不再参与过程了,只需要等待最终完成结果的通知,那么这就属于异步。

4.阻塞与非阻塞的区别:

阻塞就是发起读取数据请求的时,当数据还没准备就绪的时候,这时请求是即刻返回,还是在这里等待数据的就绪,如果需要等待的话就是阻塞,反之如果即刻返回就是非阻塞。

IO流

几种类型的IO流、区别

字节流:大多数情况我们都是使用字节流,因为大多数情况都是操作磁盘文件,所以大多数都是用的字节流的方式

字符流:如果频繁处理内存中字符串的情况,我们采用字符流,因为它具备缓冲区,提高了性能

读取大文件流的选择

字节流时,选择BufferedInputStream和BufferedOutputStream。

字符流时,选择BufferedReader和BufferedWriter

buffer读写操作过程

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

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

相关文章

北方地区长乐市污水厂(150000m3d)工艺设计

目 录 1设计说明书 3 1.1概述 3 1.1.1设计题目 3 1.1.2设计任务 3 1.1.3设计阶段(设计程度) 3 1.1.4设计依据 3 1.1.5设计原始资料 3 1.1.6设计工作量 5 1.1.7设计要求 5 1.1.8 毕业设计日期 5 1.2 设计要求 6 1.2.1 设计原则 6 1.2.3 设计内容 6 1.3 水…

PLC中ST编程的比较运算

比较运算符&#xff1a; >大于、 <小于、 >大于等于、 <小于等于、等于、 <>不等于。 BOOL类型的比较是通过1&#xff08;TRUE&#xff09;和0&#xff08;FALSE&#xff09;来比较的&#xff1b; 只有xIn_1为真&#xff0c;xIn_2为假的时候&#xff0c;xRe…

《小猫猫大课堂》1——小喵是如何开启敲代码之路的?

更新不易&#xff0c;麻烦多多点赞&#xff0c;欢迎你的提问&#xff0c;感谢你的转发&#xff0c; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真…

【Vue基础系列】vue-router 万字详解,一篇彻底搞懂

目录 一、路由的简介 二、路由基本使用 三、嵌套路由 四、路由的query参数 五、路由的params参数 六、路由的props配置 七、编程式路由导航 八、缓存路由组件 九、两个新的生命周期钩子 十、路由守卫 一、路由的简介 我们在生活中经常听到路由器&#xff0c;但关于路由…

将项目部署至云服务器的详细过程 以community项目为例

文章目录1.申请一个2核4G的云服务器&#xff0c;系统选择CentOS 7.62.使用终端连接云服务器3.使用 wget 命令下载以下安装文件4.安装jdk125.安装maven6.安装MySQL7.初始化mysql数据库8.安装Redis9.安装kafka10.安装elasticsearch及其分词工具11.安装Wkhtmltopdf12.安装tomcat13…

【Spring框架】一文带你吃透基于注解的DI技术详细教程

本文目录 文章目录本文目录&#x1f496;基于注解的DI✨概念✨[Component](https://so.csdn.net/so/search?qComponent&spm1001.2101.3001.7020)注解创建对象✨声明组件扫描器✨创建对象的四个注解✨扫描多个包的三种方式✨Value简单类型属性赋值✨Value使用外部属性配置文…

外卖项目07---git

git&#xff1a;企业、公司等 目录 一、Git概述 105 1.1Git简介 105 1.2Git下载与安装 105 二、Git代码托管服务 106 2.1常用的Git代码托管服务 106 三、Git常用命令 107 3.1Git全局配置 3.2获取Git仓库 ​编辑 ​编辑 3.3工作区、暂存区、版本库概念 3.4Git工作…

ASPICE系列:顺利通过ASPICE流程软件单元验证(SWE.4)

上次的ASPICE评估是否出了问题而您不知道原因? 或者您马上要进行第一次评估&#xff1f; 本系列文章是关于如何准备ASPICE流程软件单元验证(SWE.4)评估的。我们探究这个过程&#xff0c;预期交付以及评估人员的观点。永远记住一个想法:怎样做才能成功地通过评估? 想要成功通…

【PdgCntEditor】利用PDF目录书签编辑软件PdgCntEditor为PDF型图书快速添加书签的方法

一、给PDF加书签的两种情况 1.1 文字版PDF添加书签的理想情形 假设我们弄到了一本PDF&#xff0c;这个PDF如果是由Word或WPS转化而来&#xff0c;其中的标题也就代表了目录&#xff0c;我们可以用acrobat PDF中的AutuBookmark插件实现自动识别标题为目录的方法来添加书签。 …

『Java安全』利用反射调用MimeLauncher.run()触发RCE

文章目录前言MimeLauncherrun()MimeLauncher()反射调用MimeLauncher.run()触发RCE条件PoC完前言 rt.jar内的sun.net.www.MimeLauncher类的run方法调用了exec 据说可以有效绕过某些免杀&#xff0c;下面分析一下调用过程 MimeLauncher run() 首先&#xff1a;调用了this.m.ge…

古人的名与字、号、讳、谥有什么区别

古人复杂的名字 这个世界上想来是不存在没有名字的人&#xff0c;即便真的有人没名字&#xff0c;也会被外人赠予姓名&#xff0c;比如说一些古人典籍里的“无名氏”&#xff0c;就是专门用来形容那些没有名字也不清楚根脚的人&#xff0c;即便是现如今一些作品不知道作者是谁…

信号与线性时不变系统的傅里叶描述

1、复正弦信号和线性时不变系统的频率相应 卷积积分和卷积和傅里叶变换冲激表示信号正弦表示信号输入信号表示为延迟冲激的加权叠加输入信号为复正弦信号的加权叠加输出可以用卷积的形式来表示输出可以用傅里叶的形式来表示 (1)频率响应Frequency response 线性时不变系统对正…

Java中mybatis的Mpper代理开发的详细使用步骤

目录 前言&#xff1a; 一、全图预览 二、使用步骤 1.pom.xml里面添加依赖包 2.新建统一配置文件&#xff08;俗称数据库连接文件&#xff09; 3.新建项目 4.新建映射文件&#xff08;俗称数据库对应表xml&#xff09; 5.测试 三、文中的全部代码&#xff08;去复制可…

MySQL如何保证主备一致?

1. MySQL主备的基本原理 如下图展示的是基本的主备切换流程&#xff1a; 在状态1中&#xff0c;主库是A&#xff0c;备库是B&#xff0c;所以客户端的读写都直接方法节点A。由于节点B是节点A的备库&#xff0c;所以备库B只是将A的更新都同步过来&#xff0c;本地执行&#x…

皕杰报表使用字体和部署后添加字体

Windows系统 1、打开Win10系统的字体安装文件夹&#xff0c;可以双击打开此电脑-->打开C盘-->打开Windows-->打开Fonts&#xff1b;也可先打开计算机&#xff0c;在计算机地址栏上直接拷贝“C:WindowsFonts”路径。回车打开Win10字体文件夹。 2.下载自己需要的字体。…

数组、链表、栈、队列、树

1. 数组&#xff08;Array&#xff09; 定义&#xff1a;数组是一种 线性表 数据结构&#xff0c;它用一组 连续的内存空间 存储一组具有 相同类型 的数据。 Java中 基本数据类型数组 的存储格式&#xff1a; int arr[] new int[3]; arr[0] 0; arr[1] 1; arr[2] 2;Java中…

拿去吧你,华为出品《看漫画学Python》零基础自学首选~

目前Python在人工智能、机器学习、大数据、数据分析、网络爬虫等领域广泛应用&#xff0c;是非常适合初学者入门和培养编程兴趣的一门语言。相比较其他主流编程语言而言&#xff0c;有更好的可读性&#xff0c;和满足感&#xff0c;上手相对容易。 但是很多零基础的同学不知道…

【C语言】 函数

函数 在计算机科学中&#xff0c;子程序 &#xff0c;一个大型程序中的某部分代码&#xff0c; 由一个或多个语句块组 成。它负责完成某项特定任务&#xff0c;而且相较于其他代 码&#xff0c;具备相对的独立性。 一般会有输入参数并有返回值&#xff0c;提供对过程的封装和细…

元组啊,不就是不可变的列表吗?

B站|公众号&#xff1a;啥都会一点的研究生 相关阅读 整理了几个100%会踩的Python细节坑&#xff0c;提前防止脑血栓 整理了十个100%提高效率的Python编程技巧&#xff0c;更上一层楼 Python-列表&#xff0c;从基础到进阶用法大总结&#xff0c;进来查漏补缺 Python-元组&…

【ABAP】EXIT_SAPLMBMB_001无法Debug调试问题处理

【ABAP】EXIT_SAPLMBMB_001无法Debug调试问题处理 不久前看到SAP Community里面有这样一个问题&#xff0c;可能比较老了&#xff0c;但个人觉得比较新奇&#xff0c;就去做了下面一个测试。 首先通过事务代码“CMOD”对增强“MB_CF001”&#xff08;更新物料凭证时的客户功能出…