什么是IO多路复用?其原理和用途是什么?

什么是IO?

IO:Input/Output,即数据的读取(接收)/写入(发送)操作,针对不同的数据存储媒介,大致可以分为网络 IO 和磁盘 IO 两种。在 Linux 系统中,为了保证系统安全,操作系统将虚拟内存划分为内核空间和用户空间两部分。因此用户进程无法直接操作IO设备资源,需要通过系统调用完成对应的IO操作。

1、I/O多路复用简介

I/O 多路复用(I/O Multiplexing)是一种高效处理多个 I/O 操作的技术,常用于提高网络服务器或应用程序的并发处理能力。它允许一个线程或进程同时监控多个 I/O 操作,而无需为每个操作创建独立的线程或进程。
以下是对 I/O 多路复用的简介及其用途的详细说明:
阻塞IO非阻塞IO都是早期最常见的网络编程模型,但是他们有着致命的缺点。考虑如下场景:
在这里插入图片描述
说明:
每个用户请求都需要使用一个单独的线程进行服务,同时还要请求应用B才能完成业务逻辑。
由于不知道应用B的响应数据何时会返回,那么只能选择阻塞IO或者非阻塞IO进行轮询
然而阻塞IO会导致线程被挂起,非阻塞IO会导致线程一直处于轮询状态。这两种情况都会导致线程无法被释放或者复用。随着用户请求数的增多,应用A不得不创建更多的线程。然而对于操作系统来说,可以创建的线程是有上限的,并且过多的线程会导致线程切换的时间变多,严重时可能导致系统卡死,无法对外提供服务。这也是著名的C10K问题。
为了解决这个问题,于是人们就提出了方案:由一个或者几个线程去监控多个网络请求,由他们去完成数据准备阶段的操作。当有数据准备就绪之后再分配对应的线程去读取数据,这样就可以使用少量的线程维护大量的网络请求,这就是IO多路复用。

IO 多路复用的复用指的是复用线程,而不是IO连接;目的是让少量线程能够处理多个IO连接。

2、IO多路复用特点

  • 一个或一组线程(线程池)处理多个TCP连接
  • IO多路复用使用两个系统调用(select/poll/epoll和recvfrom),blocking IO只调用了recvfrom
  • select/poll/epoll核心是可以同时处理多个connection,而不是更快,所以连接数不高的话,性能不一定比多线程+阻塞IO好。
  • select是内核提供的多路分离函数,使用它可以避免同步非阻塞IO中轮询等待问题。

IO多路复用是一种同步IO模型,实现一个线程可以监视多个文件句柄。一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出CPU。

IO是指网络 IO,多路指多个TCP连接(即 socket),复用指复用一个或几个线程。

意思说一个或一组线程处理多个 TCP 连接。最大优势是减少系统开销小,不必创建过多的进程/线程,也不必维护这些进程/线程。

IO 多路复用的三种实现方式:select、poll、epoll

举例说明:

假设你是一名老师,让30个学生完成一道题目,并检查他们的结果是否正确,现在有以下几种情况:

1、按顺序逐个检查,先检查A,然后B,之后C、D…这中间如果有学生卡住,后面的学生都会被耽搁
2、找来30个助教,每个助教负责检查一个学生
3、站在讲台上,那个学生写完了举手示意,谁举手就去检查谁
上述场景1对应传统单线程socket模型,缺点非常明显:同时只能处理一个客户端的请求,多余的请求可以通过队列的方式保存起来,后续一次遍历处理。但如果处理某个请求时阻塞了,那么后续所有请求的处理都会阻塞。

上述场景2对应传统多线程socket模型,一般都是通过主线程阻塞等待客户端连接,每个客户端连接创建新的工作线程来处理请求的方式实现。当并发量不是很大时,这种处理方式还可以使用。一旦并发量很大,频繁创建的线程会带来巨大的资源消耗以及上下文切换消耗。

上述场景3就可以理解为I/O多路复用技术︰将客户端对应socket的fd(文件描述符)注册到select或poll或epoll上,当socket流就绪时,select线程就会执行:轮询找到就绪的socket,将它返回给应用,执行相应流处理。

从这里也就可以看出,IO多路复用技术的核心是减少服务端线程的创建,通过使用较少线程处理所有请求的方式提高整体效率。

常见I/O模型

同步阻塞IO(Blocking IO):即传统IO模型
同步非阻塞IO(Non-blocking IO):默认常见的socket都是阻塞的,非阻塞IO要求socket被设置成NONBLOCK
IO多路复用(IO Multiplexing):即经典的Reactor设计模式,也被称为异步阻塞IO,Java中的selector和linux中的epoll都是这种模型
异步IO(Asychronous IO):即Proactor设计模式,也被称为异步非阻塞IO
同步和异步是指内核通知用户线程的方式。

用户进程/线程和内核是以传输层为分割线的
传输层以上是指用户进程
传输层以下(包括传输层)是指内核(处理所有通信细节,发送数据,等待确认,给无序到达的数据排序等,这四层是操作系统内核的一部分)
同步

用户线程发起IO请求后需要等待或者轮询内核IO操作,完成后才能继续执行

异步

用户线程发起IO请求后仍继续执行,当内核IO操作完成后回通知用户线程,或调用用户线程注册的回调函数。

阻塞和非阻塞是指用户线程调用内核IO操作的方式。
阻塞

IO操作需要彻底完成后才能返回用户空间

非阻塞

IO操作被调用后立即返回给用户一个状态值,无需等待IO操作彻底完成

3、 I/O 多路复用三种实现方式说明

I/O 多路复用是一种机制,通过这种机制,应用程序可以监控多个 I/O 流(如网络连接、文件描述符等)的状态,判断它们是否可以进行读写操作,而不需要为每个 I/O 流创建独立的线程或进程。
其核心思想是将多个 I/O 操作的状态集中在一个地方进行管理,从而提高效率和资源利用率。
主要方法

  • select
    最早的 I/O 多路复用机制,通过检查一组文件描述符来判断它们是否可以进行读写操作。select 方法存在一些限制,例如文件描述符的数量限制和性能瓶颈。
  • poll
    poll 是对 select 的改进,克服了 select 的一些限制,如文件描述符数量的限制。它使用一个事件数组来跟踪文件描述符的状态。
  • epoll
    epoll 是 Linux 下的一种高效 I/O 多路复用机制,适用于大量并发连接的场景。它解决了 select 和 poll 在处理大量连接时的性能问题,支持水平触发(Level Triggered)和边缘触发(Edge Triggered)模式。
  • kqueue
    kqueue 是 FreeBSD、macOS 和其他一些 BSD 系统上的 I/O 多路复用机制,类似于 epoll,提供了高效的事件通知机制。
  • IOCP
    I/O 完成端口(I/O Completion Ports)是 Windows 上的 I/O 多路复用机制,适用于处理大量并发 I/O 操作的场景。

3、 I/O 多路复用的用途

提高并发性能

  • 高效管理大量连接
    在网络服务器中,I/O 多路复用可以高效地管理大量并发连接。通过单线程处理多个连接,减少了线程切换的开销,从而提高了整体性能。
  • 资源节约
    避免为每个连接创建一个独立的线程或进程,减少了系统资源的消耗,如内存和 CPU 时间。
    提高响应能力
  • 低延迟处理
    I/O 多路复用能够在事件发生时立即通知应用程序进行处理,从而减少了等待时间和处理延迟,提高了系统的响应能力。
  • 异步处理
    支持异步处理 I/O 操作,使得应用程序可以在处理 I/O 操作时继续进行其他工作,而不是阻塞等待。
    实现高效的网络服务
  • 高性能服务器
    许多高性能网络服务器(如 Nginx 和 Redis)使用 I/O 多路复用技术来处理大量并发连接和请求,以实现高吞吐量和低延迟。
  • 事件驱动模型
    现代的事件驱动框架和库(如 Node.js)依赖于 I/O 多路复用技术来处理并发 I/O 操作,从而实现高效的事件处理和回调机制。

5. I/O 多路复用的工作流程

1.注册事件
应用程序将感兴趣的 I/O 流(如网络连接)的状态(读、写、异常等)注册到 I/O 多路复用机制中。
2.等待事件
应用程序调用 I/O 多路复用接口,等待事件的发生。此时,应用程序会被挂起,直到注册的 I/O 流中有事件发生。
3.处理事件
当事件发生时,I/O 多路复用机制会通知应用程序。应用程序可以检查哪些 I/O 流有事件发生,并进行相应的处理。
4.重复循环
应用程序处理完事件后,可以继续注册新的事件,重复等待和处理过程。

总结

I/O 多路复用通过集中管理多个 I/O操作,避免了传统的多线程或多进程模型带来的资源开销,提高了并发处理能力和系统性能。
它广泛应用于网络服务器、高性能应用程序和事件驱动模型中,帮助实现高效的I/O 操作和响应。

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

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

相关文章

关于Excel表格隔行取列的方法

关于Excel表格隔行取列的方法 1、场景显示2、参考文章 1、场景显示 ①处的公式: INDEX($B3:$G3,(COLUMN(A1)*2)) $B与$G可以限制列不变; COLUMN(A1)返回1; 含义: 在选定区域选择偶数列的数据; 如果是奇数列的话是(COL…

查看RAM和Flash

0 Preface/Foreword 1 查看方法 1.1 map文件中查看 1.1.1 RAM可用情况 在map文件中,搜索字符串:free_ramcp 该字段表示剩余可用的RAM大小,前面对应的是hexadecimal的数值(单位Byte),就是剩余可用的RA…

乱弹篇(39)请珍惜懂你的人

今日清晨,笔者照常去到古镇味江河畔垂钓,呼吸着凉爽晨风轻轻吹拂而来的大自然氧吧生产出的优质氧气......忽地,记起已经许久未履行义务了,所以本“人民体验官”今天要推广人民日报官方微博文化产品《有个真朋友是一生的福气》。 截…

Redis:十大数据类型

键(key) 常用命令 1. 字符串(String) 1.1 基本命令 set key value 如下:设置kv键值对,存货时长为30秒 get key mset key value [key value ...]mget key [key ...] 同时设置或者获取多个键值对 getrange…

实验21.实现 printf

已完成实验 已完成实验链接 简介 实验 21. 实现 printf 总结 简化系统调用和中断,用 eax 代表调用号参数,ebx,ecx,edx 来代表参数(syscall.c kernel.s) 添加 write 的系统调用接口(syscall.c, syscall-init.c, print.s) 注意:要更改 p…

基于N32L406MB EasyFlash参数(key-value)记录库移植

EasyFlash 感谢作者的分享https://github.com/armink/EasyFlash EasyFlash是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发 三大实用功能 ENV快速保存产品参数(key-value),支持 写平衡(磨…

最小例程上加OLED显示

最小例程上加OLED显示 本工程代码链接: https://ww0.lanzoul.com/i8lNa265gj7g 失效联系:qq2958360390 我们其实就加上这几个文件, 然后会调用就可以了, 具体的就看江协科技的OLED, 讲的很清楚, 我们这里只说应用, 我们的重点在使用. 下面跟着我来, 复制黏贴: 更详细请看哔哩…

从零开始学习机器学习,掌握AI未来的关键!

从零开始学习机器学习 1. 介绍1.1 人工智能(AI)概述1.2 机器学习在人工智能中的应用1.3 机器学习基础概念 2. 监督学习2.1 什么是监督学习2.2 回归分析2.3 分类问题2.4 模型评估和选择 3. 无监督学习3.1 什么是无监督学习3.2 聚类算法3.3 降维技术 4. 深…

(39)智能电池

文章目录 前言 1 通过任务规划器进行设置 2 补充信息 3 限制条件 4 参数说明 前言 虽然还不是很普遍,但智能电池更容易从飞行器上安装和拆卸,并且能够提供更多关于电池状态的信息,包括容量、单个电池电压、温度等。 ArduPilot 支持几种…

qt的信号槽连接成功,但是就是无法触发槽函数。你必须使用connect的第5个参数,Qt::QueuedConnection

signals:void sends(); public slots:void sl();//这种是默认自动连接,故第五个参数不用写connect(this,&MainWindow::sends,this,&MainWindow::sl);emit sends();void sl() {}如果connect连接成功,但是无法触发槽函数。你应该使用第五个参数&…

【vue-cli】vue-cli@2源码学习

vue-cli 2 源码 @vue/cli: 3.11.0创建项目 vue create 项目名称 @vue/cli: 2.x.x 创建项目 vue init webpack yhh-project 脚手架初始化项目流程: 下载vue/cli@2 源码 下载完成后初始化 npm i 创建项目 vue init webpack yhh-project vue-init: bin/vue-init #!/usr/bin/e…

与Zoom集成获取会议开始和结束事件

一、注册一个Zoom免费帐号(需要在国外注册,国内不允许) 二、进入Zoom应用市场创建一个应用 点击”发展”(开发)菜单,选择构建应用。 同意条款: 选择应用类型: 设置应用信息&#x…

Linux进程控制——进程程序替换、bash的模拟实现

文章目录 exec系列函数execlexeclp和execle execv系列函数bash的模拟实现实现思路完整代码其他问题 在学习进程的时候,我们想fork一个子进程,然后就可以给他布置任务了 但是如果我们分成两个人开发,父子进程分别负责不同的任务,等…

编程小白如何成为大神?大学新生的最佳入门攻略

目录 方向一:选择适合的编程语言 方向二:制定有效的学习计划 方向三:避免常见的学习陷阱 方向四:额外建议 编程已成为当代大学生的必备技能,但面对众多编程语言和学习资源,新生们常常感到迷茫。如何选择…

深度学习模型服务端部署——flask+gunicorn+supervisor+nginx+docker

前言:深度学习模型经过前期的训练调优评估,最终得到一个精度速度满足要求的模型(.pth, .ckpt,或者.onnx等等格式),但模型要实际用起来,还得部署起来,部署分为在移动端芯片上和服务器上。在移动端芯片部署通…

大龄程序员转型攻略:拥抱人工智能,开启新征程

前言 随着科技的飞速发展,人工智能浪潮席卷全球,相关岗位炙手可热。在这个背景下,许多大龄程序员开始思考如何转型,以适应时代的变化。结合自身编程基础,大龄程序员可以学习机器学习、深度学习算法,投身于…

蓝桥杯 Python 研究生组-2023-省赛-工作时长

蓝桥账户中心https://www.lanqiao.cn/problems/3494/learning/ 问题描述 小蓝手里有一份 20222022 年度自己的上班打卡记录文件,文件包含若干条打卡记录,每条记录的格式均为“yyyy-MM-dd HH:mm:ssyyyy-MM-dd HH:mm:ss”,即按照年-月-日 时:…

转录组数据去批次方法整理(combat,combat-seq,removeBatchEffect)

为什么需要去除批次效应? 批次效应是指样本在不同批次处理及测量的情况下引入与生物学情况不相关的技术误差,比如不同试剂耗材,不同操作者,不同的实验时间等。 正是因为这些非生物学的因素存在就有可能会导致我们的结果偏离真实…

网络通信---UDP

前两天做了个mplayer项目,今日继续学习 网络内容十分重要!!! 1.OSI七层模型 应用层:要传输的数据信息,如文件传输,电子邮件等(最接近用户,看传输的内容类型到底是什么) …

精进日常:每日练习与明智取舍的艺术

目录 题目1.对于非运行时异常,程序中一般可不做处理,由java虚拟机自动进行处理。2.下面哪个关键字可以用于Java的构造方法上?3.以下代码执行的结果显示是多少( )?注解总结 题目 选自牛客网 1.对于非运行时…