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

news2025/1/12 1:56:00

什么是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.coloradmin.cn/o/1968895.html

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

相关文章

计算机毕业设计Hadoop+Hive专利分析可视化 面向专利的大数据管理系统 专利爬虫 专利数据分析 大数据毕业设计 Spark

《Hadoop专利大数据分析可视化系统》开题报告 一、选题背景与意义 随着信息技术的飞速发展,全球数据量呈现爆炸式增长,特别是在专利领域,数据的积累和更新速度更是惊人。专利数据不仅包含了技术创新的详细信息,还反映了行业的发…

Java数据结构(五)——栈和队列

文章目录 栈和队列栈基本概念栈的模拟实现集合框架中的栈栈的创建栈的方法栈的遍历 栈的应用及相关练习括号匹配逆波兰表达式求值出栈入栈次序匹配最小栈 几个含"栈"概念的区分 队列基本概念队列的模拟实现循环队列双端队列集合框架中的队列队列的创建队列的方法队列…

嵌入式day16

结构体与共用体 概述 通常结构体名第一个字符大写 } ; 分号不能省略 类型名与变量名的关系 :抽象与具体的关系 . :结构体成员运算符 先有类型,再有定义 Student 可省略 使用者只能用全局变量s1,s2 全部初始化&am…

Redis缓存常见问题

Redis 缓存的穿透、雪崩、击穿是三种常见的问题,它们各自的表现和应对策略有所不同。以下是这三者的区别: 1. 缓存穿透(Cache Penetration) 现象: 缓存穿透是指客户端请求的数据在缓存中不存在,同时在数据库中也不存…

【avue+vue2+elementui】删除、rules、页面跳转和其他问题

一、删除 API/*** 删除.* @param {*} data * @returns 返参*/ export const deleteOrder = (data) => {return request({url: /api/Order/deleteOrder,method: post,data}) }HTML左菜单<template slot="menuLeft"><el-button size="small" typ…

余弦函数的希尔伯特变换过程推导

做例2.11.1的第一个公式&#xff0c;我懒得手写了&#xff0c;直接画图了。 我曾经百度了coswt的傅里叶变换的公式&#xff0c;发现百度的公式和我换元的不一样&#xff0c;我还以为我错了&#xff0c;大致考虑了傅里叶变换的过程之后&#xff0c;我确定&#xff0c;百度的余弦…

搭建日志系统ELK(二)

搭建日志系统ELK(二) 架构设计 在搭建以ELK为核心的日志系统时&#xff0c;Logstash作为日志采集的核心组件&#xff0c;负责将各个服务的日志数据采集、清洗、过滤。然而缺点也很明显&#xff1a; 占用较多的服务器资源。配置复杂&#xff0c;学习曲线陡峭。处理大数据量时…

通过阿里云OOS“快速设置”快速配置多地域运维任务

1. 介绍 什么是系统运维管理OOS? 系统运维管理OOS&#xff08;CloudOps Orchestration Service&#xff09;是阿里云提供的一项云上自动化运维服务&#xff0c;旨在帮助用户实现运维任务的自动化管理和执行。通过OOS&#xff0c;用户可以设计模板来详细定义执行任务的内容、…

软件开发人员如何有效提问

引子&#xff1a;小张的困惑 小张是一名刚入职的大数据开发工程师&#xff0c;满怀热情地加入了一个处理城市交通数据的项目。然而&#xff0c;面对复杂的数据流和繁琐的ETL过程&#xff0c;他很快就遇到了瓶颈。每次在团队会议上&#xff0c;他都不知道该如何准确地表达自己的…

通过Java实现插入排序(直接插入,希尔)与选择排序(直接选择,堆排)

目录 &#xff08;一&#xff09;插入排序 1.直接插入排序 &#xff08;1&#xff09;核心思想&#xff1a; &#xff08;2&#xff09;代码实现&#xff08;以从小到大排序为例&#xff09;&#xff1a; &#xff08;3&#xff09;代码分析&#xff1a; 2.希尔排序&#xff08…

C# 串口控制 校验

1. 串口控制 using System; using System.IO.Ports; using System.Windows.Forms;namespace 串口控制 {public partial class Form1 : Form{//device1const byte DeviceOpen1 0x01;const byte DeviceClose1 0x81;//device2const byte DeviceOpen2 0x02;const byte DeviceCl…

【Canvas与艺术】六角大楼

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>六角大楼</title><style type"text/css">.cen…

【WOA】鲸鱼优化算法详细解读

鲸鱼优化算法的详细解读 目录 一、引言 二、鲸鱼优化算法的原理 三、鲸鱼优化算法的主要步骤 四、鲸鱼优化算法的特点 五、Python代码实现 一、引言 在当今的优化问题中&#xff0c;随着问题复杂性的增加&#xff0c;传统的优化方法往往难以找到全局最优解。近年来&#…

【计算机毕业设计】​720图书馆智能选座系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

仓库物品与装备物品替换

思路 1、创建UI面板以承载仓库中的物品和已装备的物品&#xff0c;以及物品名称和物品描述&#xff1b; 2、创建ItemData.cs装载物品的缩略图、描述并创建ItemData对象 3、创建一个脚本&#xff0c;声明并定义承载ItemData对象的数组、承载缩略图的数组。 4、显示缩略图、文…

6.key的层级结构

redis的key允许多个单词形成层级结构&#xff0c;多个单词之间用:隔开&#xff0c;格式如下&#xff1a; 项目名:业务名:类型:id 这个格式并非固定的&#xff0c;可以根据自己的需求来删除或添加词条。 例如&#xff1a; taobao:user:1 taobao:product:1 如果value是一个java对…

【Golang 面试 - 进阶题】每日 3 题(十一)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

提升SEO排名的谷歌外链策略

​要提升SEO排名&#xff0c;谷歌外链策略必须聚焦于外链数量和质量的合理搭配。市场上那些SEO表现优秀的网站&#xff0c;无一例外地拥有数万甚至数十万的外链&#xff0c;而且这些外链在结构上表现出复杂和多样化。这不仅仅是因为数量众多&#xff0c;还因为这些外链质量的高…

酷家乐--应用频繁报出cause java.net.SocketTimeoutException: Read timed out怎么办

涉及到网络层面的问题一般都比较复杂&#xff0c;场景多&#xff0c;定位难&#xff0c;成为了大多数开发的噩梦&#xff0c;应该是最复杂的了。下面通过一个实际的例子来阐述遇到了要怎么办。 现象 部署在矩阵机房的较多应用频繁报出toad异常&#xff0c;Encounter unknown …

嵌入式学习第13天——C语言循环结构break和continue

break和continue break 功能&#xff1a; 1.用在switch中&#xff0c;用来跳出switch的case语句;如果case没有break&#xff0c;可能会产生case穿透。 2.用在循环中(while、do..while、for..)&#xff0c;提前结束循环&#xff0c;也就是跳出整个循环。 说明&#xff1a; …