五种网络IO模型

五种模型出自:RFC标准。可参考: 《UNIX网络编程-卷一》 6.2

很多程序员是从高级语言的网络编程/文件操作了解到nio,继而了解到五种io模型的;

这五种io模型不止用于网络io

  • “阻塞与****系统调用”是怎么回事?我知道了线程.sleep()可以阻塞线程,指定sleep位可以标记状态,,但是还没见到阻塞的系统调用,,
  • 是说发动调用后阻塞?调用系统调用自动阻塞?
  • 说到底系统调用是怎么用啊,原以为是包含头文件,结果头文件是封装好的入口,,

linux网络编程一共有几种 IO 模型?NIO 和多路复用的区别?

一共有五种IO模型

  • 阻塞IO模型 BIO
  • 非阻塞IO模型 NIO
  • IO多路复用模型(select,poll,epoll…)
  • 信号驱动模型(SIGIO)
  • 异步IO(AIO,POSIX的aio_系列函数) Future-Listener机制 )

IO操作可分为两阶段看待:

1)进程向发起IO请求,等待数据准备(Waiting for the data to be ready),系统调用后进入内核态,内核操作数据到内核缓冲区

2)实际的IO操作,将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)

I/O多路复用是阻塞在select,epoll这样 的系统调用没有阻塞在真正的I/O系统调用

如recvfrom进程受阻于select,等待可能多个套接口中的任一个变为可读

IO多路复用使用两个系统调用(select和 recvfrom) ,blocking IO只调用了一个系统调用 (recvfrom)

多路复用模型中,每一个socket,设置为 non-blocking, 阻塞是被select()阻塞,而不是被 socket阻塞的

select/epoll 核心是可以同时处理多个 connection,而不是更快的处理单个connection,所以连接数不高的话,性能不一定比多线程+阻塞IO好

前四种IO模型都是同步IO操作,他们的区别在于第一阶段,而第二阶段是一样的,即在内核数据copy到用户空间时都是阻塞的。

而异步 I/O模型的进程在这两个阶段都是运行的。

阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞。

同步IO和异步IO的区别就在于第二个步骤是否阻塞,实际IO读写阶段会阻塞进程,而在异步IO中,是由操作系统帮忙做完IO工作再直接返回结果。

  • 同步是在等待什么?阻塞是通知进程后等他主动发起吗?进程是在空转等着通知,还是干着其他事情,轮询着等通知吗?

几个核心点:

  • 此处阻塞非阻塞说的是线程的状态,同步和异步说的是消息的通知机制
  • 同步需要主动读写数据,异步是不需要主动读写数据
  • 同步IO和异步IO是针对用户应用程序和内核的交互

##NIO(非阻塞IO模型)

NIO,即Non-Blocking IO,是非阻塞IO模型。

NIO存在性能问题,即频繁的轮询,导致频繁的系统调用,同样会消耗大量的CPU资源。可以考虑IO复用模型去解决这个问题。

不阻塞了,但是轮询doge

阻塞会让出cpu,轮询会一直占着cpu

非阻塞IO的流程如下:

图片

  1. 应用进程发起IO系统调用,内核态进行IO操作
  2. 应用进程轮询向操作系统内核,发起recvfrom读取数据。
  3. 操作系统内核数据没有准备好,立即返回EWOULDBLOCK错误码。
  4. 应用程序进程轮询调用,继续向操作系统内核发起recvfrom读取数据。
  5. 操作系统内核数据准备好了,从内核缓冲区拷贝到用户空间。
  6. 完成调用,返回成功提示。

对于NIO,如果TCP RecvBuffer有数据,就把数据从网卡读到内存,并且返回给用户;反之则直接返回0,永远不会阻塞。

常见的RPC框架,如Thrift,Dubbo

这种框架内部一般维护了请求的协议和请求号,可以维护一个以请求号为key,结果的result为future的map,结合NIO+长连接,获取非常不错的性能。

IO多路复用模型

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

解决轮询的方法:先阻塞进程,等到内核数据准备好了,主动通知应用进程再去进行系统调用。

  • 阻塞等于挂起吗?是说发起select()调用后,进程被阻塞,进入内核态等select调用返回?既然说阻塞与select()调用,那应该是这个意思。

IO复用模型核心思路:系统给我们提供一类函数(如select、poll、epoll函数),它们可以同时监控多个fd的操作,任何一个返回内核数据就绪,应用进程再发起recvfrom系统调用。

  • 多个Socket怎么说?等一批一起处理?后面追加的怎么办?

最简单的Reactor模式:注册所有感兴趣的事件处理器,单线程轮询选择就绪事件,执行事件处理器。

Java的Selector对于Linux系统来说,有一个致命限制:同一个channel的select不能被并发的调用。因此,如果有多个I/O线程,必须保证:一个socket只能属于一个IoThread,而一个IoThread可以管理多个socket。

另外连接的处理和读写的处理通常可以选择分开,这样对于海量连接的注册和读写就可以分发。虽然read()和write()是比较高效无阻塞的函数,但毕竟会占用CPU,如果面对更高的并发则无能为力。img

对于Redis来说,由于服务端是全局串行的,能够保证同一连接的所有请求与返回顺序一致。这样可以使用单线程+队列,把请求数据缓冲。然后pipeline发送,返回future,然后channel可读时,直接在队列中把future取回来,done()就可以了。

常见的RPC框架,如Thrift,Dubbo

这种框架内部一般维护了请求的协议和请求号,可以维护一个以请求号为key,结果的result为future的map,结合NIO+长连接,获取非常不错的性能。

IO多路复用之select

应用进程通过调用select函数,可以同时监控多个fd,在select函数监控的fd中,只要有任何一个数据状态准备就绪了,select函数就会返回可读状态,这时应用进程再发起recvfrom请求去读取数据。

图片

NIO中,需要轮询多次轮询系统调用直到可以读取数据,然而借助select的IO多路复用模型,只需要发起一次询问就够了,大大优化了性能。

select监视文件3类描述符: writefds、readfds、和 exceptfds。

调用后select函数会阻塞住,等有数据 可读、可写、出异常 或者 超时 就会返回。

但是,select有几个缺点:

  • 单个进程监听的IO最大连接数(FD,文件描述符)有限,默认是1024 (可修改宏定义) static final int MAX_FD = 1024
  • select函数返回后,是通过遍历fdset,找到就绪的描述符。(仅知道有I/O事件发生,却不知是哪几个,所以遍历所有来查找(不能随机访问的数据结构的亚子))随着数量增加而性能下降
  • 每次调用 select(),需要把 fd 集合从用户态拷贝到 内核态,并进行遍历(消息传递都是从内核到用户空间

poll

因为存在连接数限制,所以后来又提出了poll。与select相比,poll解决了连接数限制问题(用链表存储)。但是select和poll一样,还是需要通过遍历文件描述符来获取已经就绪的socket。如果同时连接的大量客户端,在一时刻可能只有极少处于就绪状态,伴随着监视的描述符数量的增长,效率也会线性下降。

IO多路复用之epoll

为了解决select/poll存在的问题,多路复用模型epoll诞生,它采用事件监听回调机制来实现,流程图如下:

图片

epoll先通过epoll_ctl()来注册一个fd,一旦基于某个fd就绪时,内核会采用回调机制,迅速激活这个fd,当进程调用epoll_wait()时便得到通知。这里去掉了遍历文件描述符的坑爹操作,而是采用监听事件回调的机制。

epoll()在2.6内核中提出的,对比select和poll,epoll更加灵 活,没有描述符限制,用户态拷贝到内核态只需要使用事件通知

优点:

  1. 没fd这个限制,所支持的FD上限是操作系统的最大文件句柄数,1G内存大概支持10万个句柄

  2. 效率提高,使用回调通知而不是轮询的方式,不会随着FD数目的增加效率下降。通过callback机制通知,内核和用户空间mmap同一块内存实现

JAVA中的I/O

1.4之前BIO

大型服务一般采用 C或者C++, 因为可以直接操作系统提供的异步IO,AIO.

NIO @Since(“1.4”)

NIO2.0 @Since(“1.7”),提供 AIO的功能,支持文件和网络套接字的异步IO.

NIO高级

Proactor与Reactor

一般情况下,I/O 复用机制需要事件分发器(event dispatcher)。 事件分发器的作用,即将那些读写事件源分发给各读写事件的处理者,就像送快递的在楼下喊: 谁谁谁的快递到了, 快来拿吧!开发人员在开始的时候需要在分发器那里注册感兴趣的事件,并提供相应的处理者(event handler),或者是回调函数;事件分发器在适当的时候,会将请求的事件分发给这些handler或者回调函数。

涉及到事件分发器的两种模式称为:Reactor和Proactor。Reactor模式是基于同步I/O的,而Proactor模式是和异步I/O相关的。

Reactor相当于去医院,先用事件分发器向操作系统挂号,等叫到号了(被通知can read 或者 can write)应用线程再去实际IO

Proactor相当于网上办理银行业务,向操作系统告知自己要把数据调动到什么地方,然后等操作系统内核线程完成了再告诉事件分发器

有点类似有DMA的硬件设备的IO,这里的NIO是面向线程的

在Reactor模式中,事件分发器等待某个事件或者可应用或个操作的状态发生(比如文件描述符可读写,或者是socket可读写),事件分发器就把这个事件传给事先注册的事件处理函数或者回调函数,由后者来做实际的读写操作。

而在Proactor模式中,事件处理者(或者代由事件分发器发起)直接发起一个异步读写操作(相当于请求),而实际的工作是由操作系统来完成的。发起时,需要提供的参数包括用于存放读到数据的缓存区、读的数据大小或用于存放外发数据的缓存区,以及这个请求完后的回调函数等信息。事件分发器得知了这个请求,它默默等待这个请求的完成,然后转发完成事件给相应的事件处理者或者回调。举例来说,在Windows上事件处理者投递了一个异步IO操作(称为overlapped技术),事件分发器等IO Complete事件完成。这种异步模式的典型实现是基于操作系统底层异步API的,所以我们可称之为“系统级别”的或者“真正意义上”的异步,因为具体的读写是由操作系统代劳的。

在Proactor中实现读:

  • 处理器发起异步读操作(注意:操作系统必须支持异步IO)。在这种情况下,处理器无视IO就绪事件,它关注的是完成事件。
  • 事件分发器等待操作完成事件。
  • 在分发器等待过程中,操作系统利用并行的内核线程执行实际的读操作,并将结果数据存入用户自定义缓冲区,最后通知事件分发器读操作完成。
  • 事件分发器呼唤处理器。
  • 事件处理器处理用户自定义缓冲区中的数据,然后启动一个新的异步操作,并将控制权返回事件分发器。

附录

相关系统调用

linux

  • recvfro
  • epoll_create() 在Linux内核里面申请一个文件系统 B+树,返回epoll对象,也是一个fd
  • epoll_ctl() 操作epoll对象,在这个对象里面修改 添加删除对应的链接fd, 绑定一个callback函数
  • epoll_wait() 判断并完成对应的IO操作

windows

  • IOCP

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

简单认识镜像底层原理详解和基于Docker file创建镜像

文章目录 一、镜像底层原理1.联合文件系统(UnionFS)2.镜像加载原理3.为什么Docker里的centos的大小才200M? 二、Dockerfile1.简介2.Dockerfile操作常用命令 三、创建Docker镜像1.基于已有镜像创建2.基于本地模板创建3.基于Dockerfile创建4.Dockerfile多阶段构建镜像 一、镜像底…

Unity Android 之 使用 HanLP 进行句子段落的分词处理(包括词的属性处理)的简单整理

Unity Android 之 使用 HanLP 进行句子段落的分词处理(包括词的属性处理)的简单整理 目录 Unity Android 之 使用 HanLP 进行句子段落的分词处理(包括词的属性处理)的简单整理 一、简单介绍 二、实现原理 三、注意事项 四、效…

课程项目设计--项目建立--宿舍管理系统--springboot后端

前要 项目设计–宿舍管理系统 文章目录 项目建立导入依赖配置文件配置目录结构config配置mybatis-plusswagger 生成实体、mapper和servicebaseEntity统一响应实例响应码接口响应码接口实现统一响应result统一分页响应 项目建立 太长了,修改一下 导入依赖 暂时先加…

echarts 饼图 值为0时页面显示undefined%的解决方案

当饼图的数据为0时,页面会出现 undefined% 的情况 值为0的数据: pieData: [{name: 分类一,value: 0,},{name: 分类二,value: 0,}, ], //饼图数据 页面显示为undefined% 我们可以通过 label 的 formatter 来进行自定义调整,具体点就是在 fo…

蓝海创意云×悦乐兔99艺术节直播首秀顺利开播

8月18日,苏州悦乐兔99艺术节直播首秀顺利开播,蓝海创意云为此次直播提供了全程技术支持,使用自主研发的vLive虚拟直播系统嵌入整个直播流程,带给观众一场不一样的全新视觉体验。 蓝海创意云x悦乐兔直播首秀顺利开播 蓝海创意云助力…

MySQL语法及常用数据类型

一、SQL语言概述 对数据库进行查询和修改操作的语言叫做SQL。SQL的含义就是结构化查询语言(Structured Query Language)。SQL包含以下4个部分: 1、数据定义语言(DDL):DROP、CREATE、ALTER等语句&#xff…

问道管理:沪指弱势震荡跌0.38%,金融、地产等板块走弱,算力概念等活跃

21日早盘,沪指盘中弱势震荡下探,创业板指一度跌逾1%失守2100点;北向资金小幅净流出。 截至午间收盘,沪指跌0.38%报3120.18点,深成指跌0.24%,创业板指跌0.62%;两市算计成交4238亿元,…

电脑找不到MSVCR120.dll怎么办?MSVCR120.dll是什么?

在我们的日常生活和工作中,电脑故障是难以避免的问题。而MSVCR120.dll文件是Windows系统中的一个重要组件,如果出现损坏或丢失,可能会导致程序无法正常运行,这个问题可能是由于系统文件损坏、病毒感染等原因导致的。因此&#xff…

神经网络改进:注重空间变化,权重参数调整,正则化, 熵的简单理解

目录 神经网络改进:注重空间变化 将高纬空间映射到地位空间便于表示(供给数据) 将地位空间映射到高纬空间进行分类聚合(达到可分状态(K-means)) 神经网络改进:权重参数调整 自注…

Android Drawable转BitmapDrawable再提取Bitmap,Kotlin

Android Drawable转BitmapDrawable再提取Bitmap&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"…

基于PaddlePaddle实现的声纹识别系统

前言 本项目使用了EcapaTdnn、ResNetSE、ERes2Net、CAM等多种先进的声纹识别模型&#xff0c;不排除以后会支持更多模型&#xff0c;同时本项目也支持了MelSpectrogram、Spectrogram、MFCC、Fbank等多种数据预处理方法&#xff0c;使用了ArcFace Loss&#xff0c;ArcFace loss…

记录首次面试2023-08-18

人生第一次面试&#xff0c;大概一个小时左右。没有问我C的&#xff0c;上来一个数据库事务&#xff0c;虽然没有复习&#xff0c;但是还是能够记住一些&#xff0c;主要问的一些事务的隔离级别&#xff0c;以及都有什么作用&#xff0c;我是举例回答的&#xff0c;客户端A和客…

[Go版]算法通关村第十三关青铜——数字数学问题之统计问题、溢出问题、进制问题

这里写自定义目录标题 数字统计专题题目&#xff1a;数组元素积的符号思路分析&#xff1a;无需真计算&#xff0c;只需判断负数个数是奇是偶复杂度&#xff1a;时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( 1 ) O(1) O(1)Go代码 题目&#xff1a;阶乘尾数0的个数思路分析&am…

高忆管理:市盈率一般多少合理?

市盈率&#xff08;PE Ratio&#xff09;是衡量一只股票估值水平的重要目标&#xff0c;其计算公式为股票当前市价除以每股收益。一般来说&#xff0c;市盈率较低的股票被认为是具有出资价值的好股票&#xff0c;而市盈率较高的股票则或许被认为是过度投机或者受商场热潮影响的…

我国55个少数民族及主要分布地区

声明&#xff1a;来源网络&#xff0c;仅供学习&#xff01;

漏洞指北-VulFocus靶场专栏-中级02

漏洞指北-VulFocus靶场专栏-中级02 中级005 &#x1f338;thinkphp lang 命令执行&#xff08;thinkphp:6.0.12&#xff09;&#x1f338;step1&#xff1a;burp suite 抓包 修改请求头step2 修改成功&#xff0c;访问shell.php 中级006 &#x1f338;Metabase geojson任意文件…

商用汽车转向系统常见故障解析

摘要&#xff1a; 车辆转向系统是用于改变或保持汽车行驶方向的专门机构。其作用是使汽车在行驶过程中能按照驾驶员的操纵意图而适时地改变其行驶方向&#xff0c;并在受到路面传来的偶然冲击及车辆意外地偏离行驶方向时&#xff0c;能与行驶系统配合共同保持车辆继续稳定行驶…

构建 NodeJS 影院预订微服务并使用 docker 部署(03/4)

一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 你好社区&#xff0c;这是&#x1f3f0;“构建 NodeJS 影院微服务”系列的第三篇文章。本系列文章演示了…

敏感信息泄露

由于后台人员的疏忽或者不当的设计&#xff0c;导致不应该被前端用户看到的数据被轻易的访问到。 比如&#xff1a; —通过访问url下的目录&#xff0c;可以直接列出目录下的文件列表; —输入错误的url参数后报错信息里面包含操作系统、中间件、开发语言的版本或其他信息; —前…

不同企业如何选择合适的CRM系统?

市场上的CRM系统千差万别&#xff0c;如何选到适合的CRM系统&#xff1f;很多企业凭借感觉盲目选型&#xff0c;结果上线后发现CRM系统功能不符合需求。这就好比买衣服&#xff0c;不试穿就买回家&#xff0c;结果发现尺码不合适&#xff0c;还不能退换。下面说说企业如何进行C…
最新文章