不同网络I/O模型的原理

目录

1、I/O的介绍

1.1、I/O 操作分类

1.2、I/O操作流程阶段

1.3、I/O分类

2、同步I/O

2.1、阻塞I/O

2.2、非阻塞I/O

2.3、I/O复用

2.4、信号驱动式I/O

3、异步I/O


前言

        在网络I/O之中,I/O操作往往会涉及到两个系统对象,一个是用户空间调用I/O的进程或者线程,另一个是内核空间的内核系统,当发生I/O操作时,会经历以下两个阶段:

  1. 等待数据准备就绪
  2. 将数据从内核拷贝到进程或线程中

因为在以上两个阶段上各有不同的情况,所以出现了多种I/O模型。

如下图所示:

关于内核态和用户态的介绍,可参考:操作系统的内核态和用户态场景-CSDN博客


1、I/O的介绍

         I/O 操作(Input/Output Operation)指的是计算机系统中与外部环境(如网络、磁盘、键盘、显示器等)进行数据交换的过程。

1.1、I/O 操作分类

1.网络输入(接收数据):

如 recv() 或 read() 函数,用于从网络连接中读取数据。


2.网络输出(发送数据):

如 send() 或 write() 函数,用于向网络连接发送数据。


3.网络连接管理:

如 accept() 函数,用于接受来自客户端的连接请求。


4.网络监听:

如 listen() 函数,用于监听进入的连接请求。

1.2、I/O操作流程阶段

通常用户进程中的一个完整I/O分为两个阶段:

 用户进程空间→内核空间 ,内核空间→设备空间;

整体模型图所示:

1.3、I/O分类

I/O分为内存I/O、网络I/O和磁盘I/O三种。

1、内存I/O

        涉及直接与计算机内存进行数据交换,如读取和写入内存中的数据。


2、网络I/O

        涉及通过网络接口进行的数据交换,例如从服务器下载文件或向服务器发送请求。


3、磁盘I/O

        涉及与存储设备(如硬盘驱动器或固态硬盘)进行数据交换,例如读取和写入磁盘上的文件。

        Linux中进程无法直接操作I/O设备,其必须通过系统调用请求内核来协助完成I/O操作。 内核会为每个I/O设备(例如硬盘、网络接口)维护一个缓冲区,缓冲区是内存中的一块区域,用于临时存储数据,以提高I/O操作的效率。

         对于一个输入操作来说,进程I/O系统调用(如 read())读取数据时,它会先看为该设备维护的缓冲区,看看是否已经有待处理的数据。没有的话再到设备(比如网卡设备)中读取(因为设备I/O一般速度较慢,需要等待)。

        如果缓冲区中没有数据,内核会发起设备I/O操作,从设备(例如网络接口卡、磁盘等)中读取数据。由于设备I/O操作通常较慢,需要时间来完成,内核会先等待数据到达设备缓冲区,再进行处理。

如下图所示:

所以,对于一个网络输入操作通常包括两个不同阶段:

        1、等待网络数据到达网卡,把数据从网卡读取到内核缓冲区,准备好数据。

        2、从内核缓冲区复制数据到用户进程空间。

⚠️注意:

        如果缓冲区中有数据:内核会直接从缓冲区中获取数据,并将这些数据复制到用户进程的地址空间。这种情况通常较快,因为数据已经在内核空间中,可以快速传递给用户进程。

小结

         Socket:在Linux中,socket是一种用于网络通信的抽象接口,提供了数据传输的机制。socket可以被看作是一个端点,允许进程通过它进行数据的发送和接收。

        流的抽象:在Linux中,socket被视为一种流(例如TCP流),它允许进程以流式方式读写数据。对于TCP协议来说,数据流是有序的、可靠的。

        流的抽象可以理解为像流水一样的数据传输方式,强调了数据传输的连续性和按序性,而不关心数据的具体格式。当使用socket进行网络通信时,网络层和传输层只处理数据的流动,应用层则负责数据的解析和处理。

        

        I/O操作:对socket的读写操作实际上是对网络流的操作。当进程发起对socket的读取操作时,内核会检查缓冲区是否有数据可用。如果有,数据会被传递给进程;如果没有,进程会被阻塞直到数据到达。


2、同步I/O

2.1、阻塞I/O

也称为BIO(Blocking I/O)。

1. 核心原理

阻塞式 I/O:每个连接由一个线程处理,线程在读写数据时会阻塞,直到数据准备好。

典型模型一请求一线程(One Thread Per Connection)。

底层机制:基于 InputStream 和 OutputStream 的阻塞操作。

整体原理图如下所示:

流程如下:

        第一步通常涉及等待数据从网络中到达,当所有等待分组到达时,它被复制到内核中的某个缓冲区。

        第二步是把数据从内核缓冲区复制到应用程序缓冲区。

        在Linux中,默认情况下,阻塞I/O的所有套接字都是阻塞的。

2.代码示例

// BIO 服务器示例
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {Socket socket = serverSocket.accept(); // 阻塞,等待连接new Thread(() -> {InputStream input = socket.getInputStream();byte[] buffer = new byte[1024];int len = input.read(buffer); // 阻塞,等待数据System.out.println(new String(buffer, 0, len));}).start();
}

3. 优点

  • 实现简单:代码结构直观,适合小规模应用。
  • 调试方便:线程模型清晰,便于排查问题。

4. 缺点

  • 性能瓶颈:高并发时,线程数激增,占用大量内存和 CPU,容易导致资源耗尽。
  • 扩展性差:不适合处理成千上万的并发连接。

5. 适用场景

  • 低并发场景:如小型客户端/服务器应用(如命令行工具、简单的 HTTP 服务)。
  • 简单协议处理:对性能要求不高的场景。

2.2、非阻塞I/O

允许应用程序在数据未准备好时不必等待,可以继续执行其他任务。

(Non-blocking I/O)模型如下所示:

流程如下:

        非阻塞的recvform系统调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没准备好,此时会返回一个error(EAGAIN或EWOULDBLOCK)。

         进程在返回之后,可以先处理其他的业务逻辑,稍后再发起recvform系统调用。 采用轮询的方式检查内核数据,直到数据准备好。再拷贝数据到进程,进行数据处理。

        在Linux下,可以通过设置套接字选项使其变为非阻塞。

总结:

        可以看到前三次调用recvfrom请求时,并没有数据返回,内核返回errno(EWOULDBLOCK),并不会阻塞进程。 当第四次调用recvfrom时,数据已经准备好了,于是将它从内核空间拷贝到程序空间,处理数据。

⚠️注意:但是将数据从内核拷贝到用户空间,这个阶段阻塞。

2.3、I/O复用

        多路监控:使用select、poll或epoll等系统调用来监控多个I/O流。当其中一个I/O流有数据可读或可写时,系统调用返回。适用于在单个线程内管理多个连接。

(I/O Multiplexing)模型如下所示:

流程如下:

        I/O多路复用的好处在于单个进程就可以同时处理多个网络连接的I/O。

        它的基本原理是不再由应用程序自己监视连接,而由内核替应用程序监视文件描述符。通过 select、poll、epoll 等机制,允许一个进程同时监视多个文件描述符,当某个文件描述符就绪时再进行 IO 操作。这种模型下,程序可以同时处理多个连接,提高了并发处理能力。

示例:

         以select函数为例,当用户进程调用了select,那么整个进程会被阻塞,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好,select就会返回。 这个时候用户进程再调用read操作,将数据从内核拷贝到用户进程。

⚠️注意:

  • 当客户处理多个描述符时,必须使用I/O复用;
  • 如果一个TCP服务器既要处理监听套接字,又要处理已连接的套接字,一般就要使用I/O复用;
  • 如果一个服务器既要处理TCP,又要处理UDP,一般就要使用I/O复用。
  • 如果一个服务器要处理多个协议或多个服务,一般就需要使用I/O复用。 

2.4、信号驱动式I/O

        该模型允许socket进行信号驱动I/O,并注册一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

模型如下图所示:

注意:

        虽然信号驱动IO在注册完信号处理函数以后,就可以做其他事情了。但是第二阶段拷贝数据的过程当中进程依然是被阻塞的。

3、异步I/O

    异步I/O的工作机制:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知我们。

异步I/O与信号驱动I/O模型区别在于:

        信号驱动式I/O是有内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。

模型如下图所示:

        异步I/O不是按顺序执行。用户进程进行aio_read系统调用之后,就可以去处理其他逻辑了,无论内核数据是否准备好,都会直接返回给用户进程,不会对进程造成阻塞。

        这是因为aio_read只向内核递交申请,并不关心有没有数据。 等到数据准备好了,内核直接复制数据到进程空间,然后内核向进程发送通知,此时数据已经在用户空间了,可以对数据进行处理。


总结

同步I/O和异步I/O的比较:

同步I/O:导致请求进程阻塞,直到I/O操作完成;
异步I/O:不导致请求进程阻塞;

简单的讲:就是是否参与了I/O操作;

        前四种I/O模型——阻塞式I/O模型、非阻塞式I/O模型、I/O复用(多路转接)和信号驱动式I/O模型都是同步I/O,第二步从数据从内核态copy到用户态的I/O操作(recvfrom)将进程阻塞。

        只有异步I/O模型是异步I/O。


参考文章:

1、【编程基础知识】网络I/O模型详解:从阻塞到异步_网络编程 阻塞-CSDN博客

2、五种I/O模型详解-CSDN博客

3、【网络编程下】五种网络IO模型-CSDN博客

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

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

相关文章

在正则表达式中语法 (?P<名字>内容)

&#x1f3af; 重点解释&#xff1a;?P<xxx> 是什么语法&#xff1f; 这一整段&#xff1a; (?P<xxx>...)是 Python 正则表达式中 “命名捕获组” 的语法。 咱们现在一个字一个字来解释&#xff1a; ✅ (?...) 是干啥的&#xff1f; 这是一个捕获组&#xff…

中兴B860AV1.1_MSO9280_降级后开ADB-免刷机破解教程(非刷机)

中兴B860AV1.1江苏移动-自动降级包 关于中兴b860av1.1顽固盒子降级教程终极版 将附件解压好以后&#xff0c;准备一个8G以下的U盘重新格式化为FAT32格式后&#xff0c;并插入电脑 将以下文件及文件夹一同复制到优盘主目录下&#xff08;见下图&#xff09; 全选并复制到U盘主目…

2025-06-13【视频处理】基于视频内容转场进行分割

问题&#xff1a;从网上下载的视频文件&#xff0c;是由很多个各种不同的场景视频片段合并而成。现在要求精确的把各个视频片段从大视频里分割出来。 效果如图&#xff1a;已分割出来的小片段 思考过程 难点在于检测场景变化。为什么呢&#xff1f;因为不同的视频情况各异&am…

ReentrantLock和RLock

文章目录 前言一、 ReentrantLock&#xff08;单机锁&#xff0c;Java 内置&#xff09;示例&#xff1a;方法详解 二、RLock&#xff08;分布式锁&#xff0c;Redisson 提供&#xff09;示例:方法详解 三、 对比总结:四、 如何选择&#xff1f; 前言 ReentrantLock 和 RLock 都…

thinkphp ThinkPHP3.2.3完全开发手册

惯例配置 应用设定 APP_USE_NAMESPACE > true, // 应用类库是否使用命名空间 3.2.1新增 APP_SUB_DOMAIN_DEPLOY > false, // 是否开启子域名部署 APP_SUB_DOMAIN_RULES > array(), // 子域名部署规则 APP_DOMAIN_SUFFIX > , // 域名后缀 如果是…

Python Day50 学习(仍为日志Day19的内容复习)

补充&#xff1a;梳理超参数调整流程&#xff08;逻辑&#xff09; 超参数调节的流程逻辑可以总结为以下几个步骤&#xff1a; 1. 明确目标 确定你要优化的模型和评估指标&#xff08;如准确率、F1值、AUC等&#xff09;。 2. 选择要调节的超参数 列出模型中影响较大的超参数…

公司网络变差的解决方法(固定IP地址冲突)

问题描述 最近公司网络变差&#xff0c;不知道为什么。&#xff08;别的同事反馈的&#xff0c;本人没有感觉变差&#xff0c;也是比较奇怪的现象&#xff09; 现象有视频会议变卡等。 调查过程 1.领导给网络公司打电话沟通&#xff0c;对面远程看了下&#xff0c;不是设备问…

使用Prometheus+Grafana+Alertmanager+Webhook-dingtalk搭建监控平台

一、监控平台介绍 1.监控平台简述普罗米修斯四件套,分别为Prometheus、Grafana、Alertmanager、Webhook-DingTalk。Prometheus一套开源的监控&报警&时间序列数据库的组合,由SoundCloud公司开发,广泛用于云原生环境和容器化应用的监控和性能分析。其提供了通用的数据…

UR机器人解锁关节扭矩控制:利用英伟达Isaac Lab框架,推动装配自动化的Sim2Real迁移

在工业制造领域&#xff0c;机器人装配长期依赖固定自动化模式&#xff0c;面临部署成本高、适配性差等挑战。多部件装配是制造业、汽车及航空航天等行业中的核心环节。传统装配系统通常针对特定任务设计&#xff0c;依赖大量人工工程部署&#xff0c;灵活性不足&#xff0c;难…

ABB 605系列

系列概述 ABB Relion605系列是专为配电网设计的保护继电器产品系列&#xff0c;代表了中低压电力系统保护领域的技术基准。基于ABB在电力保护领域数十年的经验&#xff0c;该系列集成了最新的数字信号处理技术和网络通信能力&#xff0c;为变电站自动化提供了完整的解决方案。…

Python|GIF 解析与构建(6):手搓 tk 录制工具

目录 Python&#xff5c;GIF 解析与构建&#xff08;6&#xff09;&#xff1a;手搓 tk 录制工具 一、工具功能概览 二、核心架构设计 1. 帧率控制模块 2. 屏幕捕获模块 3. 主应用模块 三、关键技术解析 1. 屏幕捕获技术 2. 帧率控制原理 3. 透明窗口实现 四、使用指…

在VBA中,提取word表格的文本时,通常有什么干扰符号,需要清除

标题 在VBA中&#xff0c;提取word表格的文本时&#xff0c;通常有什么干扰符号,需要清除 正文 解决问题提取word表格的文本时&#xff0c;通常有什么干扰符号,需要清除 在VBA中提取Word表格文本时&#xff0c;常见的干扰符号及其清除方法如下&#xff1a; ⚠️ 一、主要干扰符…

C++基础学习:深入理解类中的构造函数、析构函数、this指针与new关键字

前言 在C面向对象编程中&#xff0c;类是构建复杂程序的基本单元。今天&#xff0c;我们将深入探讨类中的几个核心概念&#xff1a;构造函数、析构函数、this指针以及new关键字。这些概念对于理解C对象生命周期和内存管理至关重要。 1. 构造函数 构造函数是类的一个特殊成员…

2025 高考游记/总结

坐标GD 新课标一卷选手 前言 思绪有点乱&#xff0c;想想从哪里说起 没想到这个博客已经三年没发过东西了&#xff0c;上次发还是初三准备特长生的时候&#xff0c;一瞬间就已经高考结束了&#xff0c;有种不真实感 对于高中的三年&#xff0c;有很多话、很多感悟想说&#xff…

Python基础之函数(1/3)

函数(基础) [函数后续还会更新两次] 一.认识函数的作用 函数就是将一段具有独立功能的代码块整合到一个整体并命名&#xff0c;在需要的位置&#xff0c;调用这个名称即可完成对应的需求 函数在开发过程中&#xff0c;可以更高效的实现代码重用 二.函数的使用步骤 1定义函…

AWS CloudFormation实战:构建可复用的ECS服务部署模板

一、前言 在云原生时代,基础设施即代码(IaC)已成为DevOps实践的核心组件。AWS CloudFormation作为AWS原生的IaC服务,允许开发人员和系统管理员以声明式方式定义和部署AWS资源。本文将深入探讨如何构建一个通用的CloudFormation模板,用于在AWS ECS(Elastic Container Servic…

GRUB2 启动配置的工作原理与优先级规则详解

一、核心组件概述 /boot/loader/entries/ 类型:目录,存储 BLS (Boot Loader Specification) 格式的启动项配置文件(如 20-custom-kernel-5.14.0.conf)。管理工具:由 grubby、kernel-install 等工具自动生成或修改。配置内容:每个文件定义一个启动项的详细参数(内核路径、…

网页版便签应用开发:HTML5本地存储与拖拽交互实践

文章目录 摘要成品显示核心功能与实现语法1. 本地存储管理2. 拖拽功能实现3. 自动保存机制4. 时间格式化处理 完整代码 摘要 本文详细介绍了一个基于HTML5的便签应用开发过程&#xff0c;重点讲解了如何利用localStorage实现数据持久化存储&#xff0c;以及如何实现流畅的拖拽…

docker compose安装Prometheus、Grafana

1、创建目录结构 mkdir -p /opt/monitoring/{prometheus,grafana} mkdir -p /opt/monitoring/prometheus/{config,data} chmod -R 777 /opt/monitoring # 确保容器有写入权限 2、准备 Prometheus 配置文件 vi /opt/monitoring/prometheus/config/prometheus.yml global:sc…

稀土化合物在生态环境的应用

稀土化合物凭借强吸附性、催化活性及环境兼容性&#xff0c;已成为生态治理的关键材料。氧化物、氯化物、磷酸盐等基础产品&#xff0c;通过灵活复配与工艺适配&#xff0c;可高效解决水体净化、土壤修复、废气处理三大核心问题&#xff0c;推动环境治理向低耗高效转型。那么&a…