【Linux | 网络I/O模型】五种网络I/O模型详解

1、数据传输过程

在 Linux 系统中,数据传输是通过 I/O 操作来实现的。I/O 操作是指数据从应用程序到内核,再到硬件设备(如磁盘、网络接口)的过程。 操作系统为了保护自己,设计了用户态、内核态两个状态。应用程序一般工作在用户态,当调用一些底层操作的时候(比如 IO 操作),就需要切换到内核态才可以进行。

服务器从网络接收的大致流程如下:
  • 数据通过计算机网络传到网卡
  • 把网卡的数据读取到socket缓冲区
  • socket缓冲区读取到用户缓冲区,之后应用程序就可以使用
核心就是两次读取操作,五种网络 IO 模型的不同之处也就在于这两个读取操作怎么交互。

2、两组重要概念

阻塞(Blocking)与非阻塞(Non-Blocking)

1. 阻塞
  • 定义:在阻塞模式下,当一个操作无法立即完成时,程序会被挂起,直到操作完成。这意味着在操作完成之前,程序会一直等待,不能继续执行其他任务。

  • 特性

    • 等待:阻塞调用会使调用线程等待操作完成。
    • 简单:编程模型较简单,易于理解和实现。
    • 效率:在等待期间,线程无法做其他有用的工作,可能导致资源浪费。
  • 例子

    • 文件读取:如果应用程序调用 read() 从文件中读取数据,但文件中没有数据,线程会阻塞,直到有数据可读。
    • 网络请求:如果应用程序发起网络请求,线程会阻塞,直到收到响应。
2. 非阻塞
  • 定义:在非阻塞模式下,当一个操作无法立即完成时,程序不会被挂起,而是立即返回。程序可以继续执行其他操作,并定期检查操作是否完成。

  • 特性

    • 立即返回:非阻塞调用会立即返回,无论操作是否完成。
    • 复杂:编程模型较复杂,需要轮询或回调机制来检查操作状态。
    • 效率:可以在等待期间执行其他任务,利用 CPU 资源更高效。
  • 例子

    • 文件读取:如果应用程序调用 read() 并且文件中没有数据,调用会立即返回,应用程序需要再次调用 read() 以获取数据。
    • 网络请求:在非阻塞网络编程中,程序发起请求后立即返回,程序通过轮询或事件机制来处理响应。

同步(Synchronous)与异步(Asynchronous)

1. 同步
  • 定义:在同步模式下,操作会按照顺序执行,后续操作必须等待前一个操作完成。程序在执行下一步之前会等待当前操作完成。

  • 特性

    • 顺序执行:操作按顺序执行,后续操作依赖于前面的操作。
    • 简单:编程模型简单,因为操作是顺序进行的。
    • 等待:在操作完成之前,程序不能执行其他任务。
  • 例子

    • 同步 I/O:应用程序发起读取文件操作,必须等到读取完成后才能继续执行其他操作。
    • 函数调用:普通函数调用会同步执行,调用者必须等待函数返回结果。
2. 异步
  • 定义:在异步模式下,操作的执行不会阻塞程序的其他操作。程序可以发起操作后继续执行其他任务,并在操作完成时得到通知(通过回调、事件或未来对象等)。

  • 特性

    • 并行执行:操作可以并行进行,程序不需要等待操作完成。
    • 复杂:编程模型复杂,需要处理回调、事件、未来对象等异步机制。
    • 效率:可以更高效地利用 CPU 资源和处理时间。
  • 例子

    • 异步 I/O:应用程序发起读取文件操作后立即返回,并可以继续执行其他任务。操作完成时,系统通过回调或事件通知应用程序。
    • 异步函数:现代编程语言(如 JavaScript、Python)提供了异步函数(如 async/await)来处理异步操作。

总结

  • 阻塞 vs 非阻塞

    • 阻塞:操作无法立即完成时,程序会等待。
    • 非阻塞:操作无法立即完成时,程序会立即返回,并可以继续执行其他任务。
  • 同步 vs 异步

    • 同步:操作按顺序执行,后续操作等待前面的操作完成。
    • 异步:操作可以并行进行,程序不需要等待操作完成,可以在操作完成时得到通知。

3、五种网络IO模型

3.1、阻塞式IO

阻塞 I/O 是最基本的 I/O 模型。在该模型中,当进程或线程执行 I/O 操作时,它会被“阻塞”,即等待操作的完成。如果操作无法立即完成,进程或线程会停止运行,直到数据准备就绪为止。简单来说,阻塞 I/O 的执行流程是“请求操作 -> 等待完成 -> 继续执行”。

3.1.1. 阻塞 I/O 的工作流程

以网络编程中的 recv(接收数据)操作为例,阻塞 I/O 的工作过程如下:

  1. 发起系统调用:应用程序通过系统调用(如 recv())请求从网络套接字中接收数据。

  2. 等待内核准备数据:内核检查该套接字是否有可用数据。如果没有数据可读,内核会让调用线程进入“阻塞”状态,并挂起该线程。

  3. 数据准备就绪:当网络数据到达(例如从远程主机接收到 TCP 数据包),内核将数据拷贝到内核缓冲区。

  4. 数据传输:数据准备好后,内核将数据从内核缓冲区拷贝到应用程序的用户空间缓冲区中。

  5. 返回结果recv() 调用返回,程序获得数据并继续执行。

在整个过程中,应用程序在 recv() 期间是“阻塞”的,即除非数据到达,进程无法继续执行。

想象你正在银行柜台办理业务。柜台的工作人员(即操作系统)负责处理你的请求(即 I/O 操作)。以下是如何用这个例子来理解阻塞 I/O:

  1. 排队等待:你(客户端)到银行柜台(服务器)前办理业务。柜台只有一个工作人员,且每次只能处理一个客户。

  2. 提交请求:你递交你的请求(例如取款请求)。此时,柜台工作人员需要时间来处理你的请求(如检查账户余额、准备现金等)。

  3. 阻塞等待:在处理你的请求期间,工作人员需要时间来完成工作。你(客户端)只能等待,不能继续进行其他业务。在这个等待期间,你无法离开柜台,也不能处理其他事务,只能在柜台前等待工作人员完成你的请求。

  4. 完成操作:工作人员完成你的请求后,将结果(例如现金)交给你。这时,你可以继续离开柜台,完成你的业务。

3.2、非阻塞式IO

非阻塞 I/O 是一种 I/O 模型,和阻塞 I/O 相反。当应用程序发起 I/O 操作时,非阻塞 I/O 不会让程序等待数据的准备情况。如果数据没有准备好,系统立即返回一个状态,表明数据尚不可用,程序可以继续执行其他操作,而不需要一直等待。非阻塞IO往往需要程序员循环的方式反复尝试读写文件描述符。

3.2.1 非阻塞 I/O 的工作流程

仍以网络编程为例,非阻塞 I/O 的 recv 操作流程如下:

  1. 发起系统调用:应用程序调用 recv() 请求从网络套接字接收数据。

  2. 立即返回:如果数据未准备好,recv() 不会阻塞程序,它会立即返回并给出一个错误或状态(如 EAGAIN),表明数据不可用。程序可以继续执行其他任务,而不是在等待数据期间被挂起。

  3. 检查数据:程序可以在适当的时间再次尝试接收数据,直到数据准备完毕为止。

  4. 完成数据接收:当数据准备就绪时,程序可以成功读取数据。

想象你在一家餐厅点餐,但这家餐厅提供的是“取号等餐”的服务模式。这类似于非阻塞 I/O 的工作方式:

  1. 提交请求:你到柜台下单后,服务员给了你一个取号。此时,服务员告诉你,食物需要一段时间准备。

  2. 不需要等待:你不用一直站在柜台前等待食物的完成,而是可以拿着号码牌去做其他事情,例如找个位置坐下,刷手机、聊天等。柜台没有阻塞你,你可以继续执行其他任务。

  3. 检查状态:你可以时不时地看一下餐厅的屏幕(或者听广播)来查看自己的号有没有叫到。如果号还没到,你继续等,但不需要一直在柜台前等待。

  4. 完成操作:当你的号码被叫到时,你前去取餐,整个过程完成。

3.3IO多路复用

I/O 多路复用是一种技术,用于在单个进程或线程中同时处理多个 I/O 操作。它允许程序同时监视多个 I/O 流(如多个网络套接字)的状态,并在数据准备好时进行相应的操作。这种技术可以显著提高资源利用率和程序的响应性。

3.3.1. I/O 多路复用的工作原理

I/O 多路复用的基本思想是:程序可以同时处理多个 I/O 操作,而不是每次只能处理一个 I/O 操作。它通过以下方式实现:

  1. 注册感兴趣的 I/O 流:程序向操作系统注册它感兴趣的多个 I/O 流,例如多个网络连接或文件描述符。

  2. 等待事件:程序调用 I/O 多路复用函数(如 select()poll()epoll()kqueue()),这些函数会阻塞程序,直到至少一个注册的 I/O 流有事件发生(如数据到达)。

  3. 处理事件:操作系统通知程序哪些 I/O 流有数据准备好或发生了其他事件,程序可以对这些事件进行处理。

假设你在一个大型活动现场工作,你需要同时协调多个任务(如管理多个会议室的活动、处理多个客户的请求等)。这类似于 I/O 多路复用的工作方式:

  1. 注册任务:你登记需要处理的所有任务,例如每个会议室的活动、客户的咨询请求等。这些任务就像 I/O 流。

  2. 等待事件:你定期检查每个任务的状态,可能会通过通信工具(如对讲机、手机)等待其他人的反馈或通知。

  3. 处理任务:当你收到任务的反馈或通知时,你立即处理相关任务,例如安排会议室的设备、回答客户的问题等。你不需要等到一个任务完全完成后才开始处理下一个任务,而是可以同时处理多个任务的状态。

3.4、信号驱动式IO

信号驱动式 I/O 是一种 I/O 模型,用于处理 I/O 操作时的事件通知。它依赖于操作系统发送信号来通知程序某些 I/O 事件的发生,从而避免了持续的轮询。这种方法通常用于处理异步 I/O 操作。

3.4.1 信号驱动式 I/O 的工作原理

信号驱动式 I/O 的基本流程如下:

  1. 设置信号处理:程序首先注册一个信号处理程序(Signal Handler),该程序会处理特定的信号(如 SIGIO)。

  2. 设置 I/O 设备为信号驱动模式:程序通过系统调用将 I/O 设备(如网络套接字)设置为信号驱动模式。这样,当设备有数据准备好时,操作系统会向程序发送一个信号。

  3. 等待信号:程序处于等待状态,直到操作系统发送信号。此时,信号处理程序会被触发。

  4. 处理信号:信号处理程序被调用来处理 I/O 事件。例如,它可以读取网络数据、处理文件操作等。

想象你在家中等待快递员送货,而你知道快递员会按门铃通知你。这个场景类似于信号驱动式 I/O 的工作方式:

  1. 设置通知:你设置好门铃,知道快递员会按门铃来通知你。这个动作类似于信号驱动式 I/O 中的信号处理设置。

  2. 等待信号:你在家中做其他事情,但你随时准备好听到门铃声。这个状态类似于程序等待信号的状态。

  3. 接收信号:当快递员到达时,他按响门铃。这个动作就像操作系统发送一个信号通知程序有 I/O 事件发生。

  4. 处理信号:你听到门铃声后,去开门接收快递。这就像信号处理程序被调用来处理实际的 I/O 事件(例如读取数据)。

3.5、异步IO

异步 I/O 是一种 I/O 操作模型,其中 I/O 操作的请求和处理是分开的。在这种模型中,程序发起一个 I/O 请求后,不需要等待操作完成,可以继续执行其他任务。当 I/O 操作完成时,系统会通知程序,程序可以根据通知来处理结果。这种模型可以提高程序的响应性和效率,特别是在处理大量并发 I/O 操作时。

2. 异步 I/O 的工作原理

异步 I/O 的基本流程如下:

  1. 发起 I/O 请求:程序发起一个 I/O 操作请求(如读取文件或网络数据),并提供一个回调函数或通知机制,用于处理操作完成后的结果。

  2. 继续执行其他任务:发起 I/O 请求后,程序可以继续执行其他任务,而不需要等待 I/O 操作完成。

  3. 等待通知:系统在后台处理 I/O 操作。当操作完成时,操作系统会通知程序。

  4. 处理结果:程序通过回调函数、事件通知或其他机制来处理 I/O 操作的结果。

设想你在餐厅里点餐,餐厅的工作流程类似于异步 I/O 模型:

  1. 发起请求:你向服务员点餐。这类似于程序发起 I/O 请求。服务员将你的点菜信息提交给厨房。

  2. 继续活动:你可以继续做其他事情,比如聊天、玩手机等。你不需要等待厨房准备食物的整个过程,而是可以继续享受你的时间。这就像程序在发起异步 I/O 请求后继续执行其他任务。

  3. 等待通知:厨房准备好你的食物后,服务员会来通知你。这个通知相当于 I/O 操作的完成通知。

  4. 处理结果:服务员将准备好的食物送到你的桌子上,你可以开始用餐。这就像程序处理异步 I/O 操作完成后的结果。

4、五种网络IO模型对比

总结比较

模型发起 I/O 请求等待 I/O 操作处理结果特点
阻塞 I/O发起请求阻塞等待完成处理结果简单易懂,但效率低
非阻塞 I/O发起请求立即返回(检查状态)处理结果轮询方式,效率较高
I/O 多路复用发起请求等待事件发生处理已就绪事件高效处理多个 I/O 操作
信号驱动式 I/O发起请求等待信号处理信号避免轮询,编程复杂
异步 I/O发起请求继续执行其他任务处理结果(回调或通知)高效处理大量并发操作

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

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

相关文章

数据库的诗篇:深入探索 MySQL 表操作的艺术与哲学

文章目录 前言🌸一、创建表——搭建数据存储的基础框架1.1 基本语法1.2 创建表的实际案例解释: 1.3 表设计的最佳实践 🌸二、查看表结构——快速了解数据库设计2.1 使用 DESC 命令解释: 2.2 使用 SHOW COLUMNS 命令2.3 使用 SHOW …

Java线程安全

目录 一.引入 二.介绍 1.概念 2.产生的原因 三.修改操作不是原子性 1.分析问题 2.解决问题(锁) 四.可重入与不可重入 五.死锁 1.引入 2.死锁的三种情况 3.构成死锁的必要条件 六.内存可见性 1.引入 2.产生原因 3.解决问题 七.指令重排序…

让你的 IDEA 使用更流畅 | IDEA内存修改

随着idea使用越来越频繁,笔者最近发现使用过程中有时候会出现卡顿现象,例如,启动软件变慢,打开项目的速度变慢等: 因此如果各位朋友觉得最近也遇到了同样的困惑,不妨跟着笔者一起来设置IDEA的内存大小吧~ …

虚拟现实在制造业中的应用

当你想到制造业中的虚拟现实技术时,你脑海中闪过的第一个念头是什么?从目前来看,只需几年时间,制造业就将离不开虚拟现实技术的帮助。实施虚拟现实应用对制造业来说都有诸多好处。通常情况下,制造设施都是由各种机器组…

基于neo4j的学术论文关系管理系统

正在为毕业设计头疼?又或者在学术研究中总是找不到像样的工具来管理浩瀚的文献资料?今天给大家介绍一款超实用的工具——基于Neo4j的学术论文关系管理系统,让你轻松搞定学术文献的管理与展示!🎉 系统的核心是什么呢&a…

一个基于.NET8+WPF开源的简单的工作流系统

项目介绍 AIStudio.Wpf.AClient 是一个基于 WPF (Windows Presentation Foundation) 构建的客户端框架,专为开发企业级应用而设计。该项目目前版本为 6.0,进行了全面优化和升级,提供了丰富的功能和模块,以满足不同场景下的开发需…

清华大学《2022年+2021年822自动控制原理真题》 (完整版)

本文内容,全部选自自动化考研联盟的:《清华大学822自控考研资料》的真题篇。后续会持续更新更多学校,更多年份的真题,记得关注哦~ 目录 2022年真题 2021年真题 Part1:2022年2021年完整版真题 2022年真题 2021年真题…

图层之间的加减法

如右图所示,正方形ABCD的边长为1cm,AC、BD分别是以点D和点C为圆心、1cm为半径作的圆弧。问阴影部分a的面积比阴影部分b小____? 这道题首先是固定的图形,形状已经确定了,按理说a和b的面积都可以求出来,但是题目问的是b…

ALIGN_ Tuning Multi-mode Token-level Prompt Alignment across Modalities

文章汇总 当前的问题 目前的工作集中于单模提示发现,即一种模态只有一个提示,这可能不足以代表一个类[17]。这个问题在多模态提示学习中更为严重,因为视觉和文本概念及其对齐都需要推断。此外,仅用全局特征来表示图像和标记是不…

颐驰06持续交付,明日科技赋能出行生活

在全球智能出行领域,自动驾驶技术的发展一直是行业关注的焦点。不久前,特斯拉发布的自动驾驶出租车引发了全球关注,但由于缺乏具体的技术细节,导致投资者信心受挫,特斯拉股票一度下跌近10%。与此同时,中国车…

springboot079信息化在线教学平台的设计与实现(论文+源码)_kaic

信息化在线教学平台的设计与实现 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了信息化在线教学平台的开发全过程。通过分析信息化在线教学平台管理的不足,创建了一个计算机管理信息化在线教学平台…

家政服务管理系统小程序ssm+论文源码调试讲解

第2章 开发环境与技术 基于微信小程序的家政服务管理系统的编码实现需要搭建一定的环境和使用相应的技术,接下来的内容就是对基于微信小程序的家政服务管理系统用到的技术和工具进行介绍。 2.1 MYSQL数据库 本课题所开发的应用程序在数据操作方面是不可预知的&…

Java后端面试题:Java基础篇

目录 Java基础 1.请你说说Java中基本数据类型的bit长度? 2.switch支持哪些数据类型?支持long么? 3.讲一下常见编码方式? 4.char能不能存储中文? 5.为什么数组索引从0开始呢?假如从1开始不行吗&#xf…

探秘 MySQL 数据类型的艺术:性能与存储的精妙平衡

文章目录 前言🎀一、数据类型分类🎀二、整数类型(举例 TINYINT 和 INT )🎫2.1 TINYINT 和 INT 类型的定义2.1.1 TINYINT2.1.2 INT 🎫2.2 表的操作示例2.2.1 创建包含 TINYINT 和 INT 类型的表2.2.2 插入数据…

【JavaSE】认识String类,了解,进阶到熟练掌握

#1024程序员节 | 征文# 下面就让博主带领大家一起解决心中关于String类的疑问吧~~~ 1.字符串构造: 第一种和第二种(有一定的区别,在常量池上) public static void main(String[] args) { // 使用常量串构造 String s1 "h…

最新PHP网盘搜索引擎系统源码 附教程

简介 最新PHP网盘搜索引擎系统源码 附教程 这是一个基于thinkphp5.1MySQL开发的网盘搜索引擎,可以批量导入各大网盘链接,例如百度网盘、阿里云盘、夸克网盘等。 功能特点:网盘失效检测,后台管理功能,网盘链接管理&a…

(三)第一个Qt程序“Qt版本的HelloWorld”

一、随记 我们在学习编程语言的时候,各种讲解编程语言的书籍中通常都会以一个非常经典的“HelloWorld”程序展开详细讲解。程序虽然简短,但是“麻雀虽小,五脏俱全”,但是却非常适合用来熟悉程序结构、规范,快速形成对编…

axure中继器

学习了一点中继器,完成管理后台左侧菜单的功能设置。 样式不太好看,只分享功能!这篇写的有点潦草,只供参考。 点击展开隐藏一级菜单 下面是配置交互信息 二级菜单要组合,加载时隐藏,点击一级菜单切换显隐…

在linux系统中查看具体文件大小命令

#!/bin/bash# 检查是否提供了路径 if [ "$#" -ne 1 ]; thenecho "用法: $0 <路径>"exit 1 fiDIRECTORY$1# 检查路径是否存在 if [ ! -d "$DIRECTORY" ]; thenecho "错误: 目录 $DIRECTORY 不存在."exit 1 fi# 定义命令数组 comm…

Linux:定时任务

目录 服务 配置命令 配置格式 定时任务案例 每2分钟同步时间 每天半夜备份文件 服务说明 相关目录&#xff1a; /var/spool/cron/ 用户的定时任务配置文件目录&#xff08;用户制定的任务都在该目录&#xff09; /var/log/cron 定时任务日志 /etc/crontab 系统定时任…