4种I/O模型简介

news2024/11/26 14:24:23

目录

1、同步阻塞IO(BIO)

2、同步非阻塞IO(NIO)

3、多路复用IO

3.1、select(轮询)

3.2、poll(轮询)

3.3、epoll(事件驱动)

3.4、select、poll、epoll总结

4、异步IO模型(AIO)


网络IO涉及的两个对象:用户线程 + 系统内核。

当一个read发生时,会经历两个阶段:

  1. 数据准备:将数据复制到内核态Buffer中。数据准备阶段,数据可能还未发送完,或者正在发送途中,此时内核态Buffer中的数据并不完整。
  2. 数据复制:将内核态Buffer中的数据复制到用户态的Buffer中。

阻塞和非阻塞描述的是用户线程调用内核IO操作的方式;

同步和异步描述的是用户线程与内核的交互方式。

  • 阻塞:IO操作需要彻底完成后,才返回到用户线程执行用户操作。
  • 非阻塞:IO操作被调用后,立即返回一个状态值给用户线程,用户线程就可以去做其他操作。
  • 同步:用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行。
  • 异步:用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

1、同步阻塞IO(BIO)

面向流,同步阻塞IO。服务器一个线程只处理一个客户端的连接。

在IO执行的两个阶段(数据准备和数据复制),用户线程都是阻塞的。

  • 数据准备:系统内核还未接收到一个完整的TCP包,需要等待足够的数据到来。此时用户线程进入阻塞状态。
  • 数据复制:系统内核等到数据准备好了,会将数据从内核Buffer中拷贝到用户内存中,然后返回结果,用户线程才会解除线程阻塞状态。

优点:在阻塞等待数据期间,用户线程挂起,基本不占用CPU资源。

缺点:高并发场景下,需要大量线程来维护大量网络连接,内存、线程切换开销巨大。

2、同步非阻塞IO(NIO)

用户线程发起read请求:

  • 内核数据未准备好:当内核中的数据还未准备好时,内核会立刻返回一个错误给用户线程;
  • 线程轮询:如果用户线程接收到内核返回的错误状态,用户线程会不断向内核发起read操作;
  • 内核数据已准备好:当系统内核中的数据准备好后, 用户线程阻塞,内核开始复制数据到用户内存,然后返回结果;用户线程读取到数据后,解除阻塞状态。

优点:在内核等待数据的过程中,用户线程不会阻塞。

缺点:内核等待数据过程中,用户线程会不断轮询内核,发送read请求,占用较多的CPU资源。

3、多路复用IO

  • 多路:多个TCP连接(即socket或者channel)
  • 复用:复用一个或几个线程。

即:同一个线程内同时处理多个TCP连接。 优势是减少系统开销,不必创建/维护过多的线程。

        为了避免Nio模型中的轮询等待问题,有了IO多路复用模型,也叫做事件驱动IO(Reactor设计模式),基本原理就是有个函数会不断地轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。

多路复用IO一句话总结:在一个进程里面开辟多个通道,然后进程会去轮询准备就绪的通道,被选中的通道去进行读写操作

Reactor: 事件分派器,负责事件的注册,删除以及对所有注册到事件分派器的事件进行监控, 当事件发生时会调用Event Handler接口来处理事件。

流程如下:

  • 用户线程注册事件处理器,之后可以继续执行做其他的工作(异步)。
  • Reactor线程负责调用内核的select/poll/epoll函数检查socket状态。
  • 当有socket被激活时,通知相应的用户线程(或执行用户线程的回调函数),执行handle_event进行数据读取、处理的工作。
  • 用户线程发起IO请求,读取数据,进行后续业务处理。发起请求时,数据已经到达,所以用户线程不会阻塞。

3.1、select(轮询)

  • Select连接文件描述(socket)有限制,默认1024,由FD_SETSIZE设置,采用数组存储。
  • 在检查是否有socket需要读写时,轮询,采用线性扫描。
  • 每次调用select,都需要把fd_set集合从用户态拷贝到内核态,并在内核遍历传递进来的fd_set,开销大。

3.2、poll(轮询)

        Poll模型和selector模型没有本质区别:别在于selector模型有注册数量限制1024,而poll没有限制,因为poll是基于链表存储的。

3.3、epoll(事件驱动)

        基于事件驱动的IO方式,没有文件描述符(socket)限制,epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中这样在用户空间和内核空间的copy只需一次。

  • epoll 没有最大并发连接的限制,上限是最大可以打开文件的数目,如:1GB内存的机器上大约是10万左右
  • 效率提升, epoll 最大的优点就在于它只管你活跃的连接 ,而跟连接总数无关,因此在实际的网络环境 中, epoll 的效率就会远远高于 select poll
  • epoll使用了共享内存,不用做内存拷贝

3.4、select、poll、epoll总结

4、异步IO模型(AIO)

读操作流程如下:

  • 用户线程向内核发起异步read请求,向内核注册某个IO操作;
  • 请求立即返回,此时用户线程不阻塞,可以去做其他操作;
  • 内核完成数据准备和数据复制操作后,内核会给用户线程发送一个信号,或者调用用户线程注册的回调函数,告诉用户线程read操作完成;
  • 用户线程读取用户缓冲区的数据,执行线程的后续操作。

优点:真正的异步输入输出,吞吐量高。

缺点:应用程序仅需要进行事件的注册和接收,其余工作都留给了操作系统,需要底层内核支持。

以上内容为个人学习理解,如有问题,欢迎在评论区指出。

部分内容截取自网络,如有侵权,联系作者删除。

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

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

相关文章

Kotlin中嵌套类、数据类、枚举类和密封类的详解

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家 👉点击跳转到教程 一、嵌套类 如果一个类只对另一个类有用,那么将其嵌入到该类中并使这两个类保持在一起是合乎逻辑的&#xf…

【Deepstream学习】TX1 跑demo

大家好,我是虎哥,使用NVIDIA Jeston TX1 也有很长一段时间了,由于这是基本停产的一个模块,其实自己也担心有很多官方的demo无法适配跑起来了,所以花了点时间,进一步研究发挥其GPU性能,使用各种硬…

STM8S207时钟管理库函数

STM8S207时钟树 //STM8S207时钟管理库函数 //CLK_DeInit();//将相关的时钟寄存器恢复到默认值 //CLK_HSECmd(ENABLE);//启用外部高速振荡器HSE //CLK_HSECmd(DISABLE);//关闭外部高速振荡器HSE //CLK_HSICmd(ENABLE);//启用内部高速振荡器HSI //CLK_HSICmd(DISABLE)//关闭内部高…

Spring Cloud Sentinel(限流、熔断、降级)、SpringBoot整合Sentinel、Sentinel的使用-60

一:Sentinel简介 Sentinel就是分布式系统的流量防卫兵 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 1.1 官方文档 官方文档&#…

哪里可以找到电子版的大学课本?

第一个:中国高校课件下载网站网址:http://download.cucdc.com/这是一个可以下载各个大学课本的网站,基本上所有的大学课本都能在这里找到PDF版本。可以按学校学科搜。 第二个:淘链客网址:https://www.toplinks.cc/s/PD…

MySQL_存储引擎

存储引擎 MySQL体系结构 连接层 最上层是一些客户端和链接服务,主要完成一些类似于连接处理、授权认证、及相关的安全方案。服务器也会为安全接入的每个客户端验证它所具有的操作权限。 服务层 第二层架构主要完成大多数的核心服务功能,如SQL接口&…

读书:《如何想到又做到》

全书最有用的内容是下面这张图:持久改变的SCIENCE模型。 作者为了方便读者记忆,找了7个单词,首字母拼在一起就是SCIENCE,对应着7种武器: S 阶梯(Stepladders):小而又小的迭代 C 社群…

高性能零售IT系统的建设09-Spring Boot2.4.2+Spring Cloud+Nacos+Feign+Hystrix的生产级应用实例

开篇 通过前面8篇我们已经感受到了我接手时这个项目有多“烂”,当然喽如果只是一味的承认它的烂这不是积极乐观主义。 我在接触管理早期听过一次四大厂的报告,报告中说到:从来没有屎一样的团队只有屎一样的“带队”。 这也符合我们一直接受的…

SpringMVC @RequestHeader @CookieValue 处理获取请求参数的乱码问题

SpringMVC RequestHeader CookieValue 处理获取请求参数的乱码问题RequestHeaderCookieValue什么是cookie通过POJO获取请求参数通过CharacterEncodingFilter处理获取请求参数的乱码问题get请求的乱码post请求乱码处理获取请求参数的乱码问题)RequestHeader 1.RequestHeader是将…

实时计算业务介绍实时日志分析

4.1 实时计算业务介绍 学习目标 目标 了解实时计算的业务需求知道实时计算的作用应用 无 4.1.1 实时计算业务需求 实时(在线)计算: 解决用户冷启动问题实时计算能够根据用户的点击实时反馈,快速跟踪用户的喜好 4.1.2 实时计算…

编译与优化

第10章 前端编译与优化 10.2.1 Javac的源码与调试 从Javac代码的总体结构来看,编译过程大致可以分为1个准备过程和3个处理过程,它们分别如下 所示。 1)准备过程:初始化插入式注解处理器。 2)解析与填充符号表过程&…

【C++】异常

​🌠 作者:阿亮joy. 🎆专栏:《吃透西嘎嘎》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉C语言传统…

精神财富 物质财富

今天聊到别的家庭每天都制定好计划的,补习班 party 冬令营什么之类的,这个是我们达不到的。有人提前开启了认知,赚到了人生的第一桶金。懂得付出,和执行输出差了好多数量级。 今天看了杂技表演,男人和女人配合的好好 …

C++ 初阶 :stackqueue

文章目录1 stack的介绍2 stack的模拟实现3 queue的介绍4 queue的模拟实现5 priority_queue(优先级队列)介绍6 priority_queue 模拟实现7 仿函数8 deque的简单介绍8.1 deque与vector list的比较8.2 为什么选择deque作为stack和queue的底层默认容器1 stack的介绍 ①stack是一种容…

Springboot校园食堂外卖点餐系统357

目 录 1 概述 1 1.1课题背景及意义 1 1.2 国内外研究现状 1 1.3 本课题主要工作 2 2 系统开发环境 3 2.1 java简介 3 2.2 Mysql数据库 3 2.3 B/S结构 4 2.4 JSP技术介绍 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2操作…

javaEE 初阶 — Socket 套接字与 UDP 数据报套接字编程

文章目录1. Socket 套接字1.1 有连接与无连接1.2 可靠与不可靠传输1.3 面向字节流与面向数据报1.4 全双工与半双工2. UDP数据报套接字编程2.1 DatagramSocket API2.2 DatagramPacket API2.3 InetSocketAddress API3. UDP 版本的客户端服务器程序3.1 服务器实现3.2 客户端实现3.…

【JUC并发编程】Java内存模型——JMM

【JUC并发编程】Java内存模型——JMM详解 文章目录【JUC并发编程】Java内存模型——JMM详解一:并发编程模型的两个关键问题二:Java内存模型的抽象结构1:从 CPU 缓存模型说起2:JMM3:JMM与Java内存区域划分的区别与联系4…

(考研湖科大教书匠计算机网络)第三章数据链路层-第二节:封装成帧

专栏目录首页:【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一:封装成帧概述二:封装成帧作用(1)帧定界A:概述B:注意(2)透明传输A:字符填充B&…

设置Linux的信任列表

前言 我们在使用普通用户的时候,我们可以对指令提权,需要用到sudo指令,但是我们在使用的时候会报错。 原因就是,我们linux系统不信任你,必须将你放到我们的信任列表中,我们就可以使用我们的指令提权。 下图是我们在不是…

数据库系统概论②——关系数据库基础

本篇文章主要讲解关系数据库基础中的基本概念,包括关系模型概述、关系的完整性约束等等内容。 同时想要了解更多数据库系统概论知识的朋友可以看下我的上一篇文章数据库系统概论①——数据库系统基本概念 文章目录1、关系数据库的基本概念1.1 关系模型概述1.2 关系数…