说说什么是IO多路复用?以及其演进过程。

news/2024/10/31 5:26:51/

文章目录

      • 1.阻塞IO模型(BIO)和 非塞IO模型(NIO)
      • 2.什么是IO多路复用?
      • 3.IO多路复用的演进?

1.阻塞IO模型(BIO)和 非塞IO模型(NIO)

阻塞IO模型(BIO):
如果我们为每一个连接创建一个线程,连接结束时做对应的销毁,这种情况下,如果连接中没有数据可读的话,线程就不得不阻塞,直到连接可读。这个时候就算其他的连接有数据可读,阻塞的线程也是没有机会去处理的。
服务端整个过程只有一个线程,依次循环处理客户端的socket,这种情况下,客户端的某个socket阻塞住了,是会影响到其他的客户端的处理的,必须等待阻塞的客户端处理结束才能接着处理接下来的请求.
非塞IO模型(NIO):
在线程读取数据的时候,如果数据不可读,线程会立即拿到返回,然后去处理别的逻辑。等一会线程再尝试读取数据,这样反复处理,这里就需要一个轮询的逻辑,因为读数据的一端,也不知道数据什么时候可读,所以就需要每间隔一段时间去看看。
非塞IO模型(NIO)相较于阻塞IO最大的特点就是同步非阻塞在进行系统调用的时候,也就是accept和read调用的时候,是不会被阻塞的。socket的相关操作(read、write)都是需要在内核态进行完成的,不能在用户态进行完成,内核态通过将这些函数进行封装,通过像read跟write这种函数提供出来
优点:单个socket阻塞的话,是不会影响到其他的socket
缺点:要不断的在客户端遍历需要建立连接的fd,不断的进行系统调用(会涉及到用户态和内核态的切换),需要一定的开销的。

2.什么是IO多路复用?

IO多路复用(出发点就是要设计一个高性能的网络服务器,这个网络服务器可以供多个客户端建立连接,并且能处理多个客户端的请求。。能想到的就是写多线程去处理,其实现在很多的rpc框架就是用到了这种方式,多线程的弊端就是需要不断地进行上下文的切换,需要处理一些上下文的切换(占用内存的瓶颈),这个过程很繁琐,并且会造成资源的浪费,比如有一千个客户端和服务端建立连接,就需要创建一千个线程,但在同一时刻可能就只有三四个建立连接,这就会造成资源的浪费,因而多线程并不是一种最好的解决方式,那么如何用单线程的方式处理):

就是一个线程如何处理多个连接请求的过程和技术,我们不需要为每个连接创建一个处理线程等待数据可读或可写,IO多路复用会在IO准备好的时候主动通知我们,我们用一个线程就可以完成对全部IO通讯的很监听。。IO多路复用被用来解决性能的问题,解决的办法1:资源复用,多个网络IO复用一个或者多个线程来处理请求. 2.线程不需要等待时间被触发,IO事件被触发的时候能直接通知应用程序,要实现这种线程池的处理方式,就需要引入了一个中间层,所有网络连接在中间层上进行注册,而程序也需要阻塞在这个中间层上,等待他的事件通知,这个中间层便是经常提及的SELECT、EPOLL。

FD:文件描述符,非负整数。linux下一切皆文件,linux中的一切资源都可以通过文件的方式访问和管理,fd就是文件的索引,指向某个文件资源,内核利用fd来访问和管理资源。

同步阻塞:服务端每次只会和一个客户端建立连接,要么就阻塞等待,客户端建立连接
同步非阻塞:服务端每次只会和一个客户端建立连接,他不会被阻塞,如果没有就绪的事件时,非阻塞IO会马上返回一个负数的fd,如果服务端没有和客户端建立上连接,他会返回一个非负的fd继续进行轮询,见下图

总结:同步非阻塞IO其实就是操作系统底层,对同步阻塞IO做了一些优化,提供了一种解决问题的方式,从而避免了单个socket影响到其他socket的情况
缺点:同步非阻塞IO需要我们在用户空间不断的去遍历(涉及到用户态到内核态的一个调用,会是一个问题)调用read函数来检查是否有数据到来。
在这里插入图片描述

3.IO多路复用的演进?

  • select:
    下面的函数中nfds传入的是三个集合描述符的最大值加一,也就是告诉内核,三个集合里面的fd就是这么大,,你只需要检查到这个地方就可以了,而不用做一些无用的检查。
    timeval代表的是超时事件,就是马上判断,判断没有就绪的时候,经过多长时间进行返回。如果是-1,那么就一直等待,直到有就绪的时候才进行返回
    服务端监听4个socket,我们拿到四个socket对应的一个fd,当我们在用户空间调用select函数的时候,首先会先将这四个fd拷贝一份到内核空间,接着内核空间会来遍历这4个fd,就是会依次检查每个fd上对应的socket有没有数据到来,就是有没有就绪,如果没有的话,接着往下检查,直到他检查到某个fd有数据可读了,这个时候,它会将这个fd打上一个标记,然后返回fd的就绪的数量。返回之后,用户空间知道有fd就绪了。,但是他不知道具体是哪一个,所以用户空间就是遍历fd集合找到最终的就绪的fd,然后对就绪的fd进行数据的处理。然后继续下一个fd的调用。
    如果在内核态遍历一次发现4个fd都没有就绪,这个时候内核空间一种就是继续下一次的遍历,一直遍历,直到有一个fd就绪了才终止遍历,将这个fd打标返回给用户空间,这种方法会占用大量的CPU。
    具体的实现其实是遍历一次之后发现没有就绪的,他会把当前的一个用户进程阻塞起来,当客户端向服务端发送数据的时候,数据通过网络到服务端的网卡,网卡通过DMA的方式将这个数据包写入到指定的内存,处理完之后通过中断信号告诉CPU有新的数据到达了,CPU收到中断信号后会进行响应中断,调用中断的处理程序进行处理,首先就是根据这个数据包的ip跟端口号找到对应的这个socket,然后将数据保存到socket队列,然后在检查socket对应的等待队列里是不是有进程在阻塞等待 ,如果有的话,唤醒该进程,用户进程唤醒后,再继续检查一遍这个fd集合,检查到某个fd就绪后,就给这个fd打标,然后结束阻塞,返回给用户
    就绪的文件描述符复用了 readset。用的是bitmap位图,发送的时候代表的是哪些文件描述符是需要检查的,返回的是准备就绪的文件描述符的标记。
    在这里插入图片描述
    在这里插入图片描述
  • Poll:
    poll整体的话跟select是比较类似的,主要是在数据结构上进行了一些优化,
    优化一:存储监听的事件和就绪的事件,所以就不用每次调用完之后进行重置,的限制的
    优化二:层是传入的一个链表,用户传入的时候是一个数组,但是拷贝到内核,它是通过链表存储要监听的文件描述符,这个链表他是没有
    问题:
    1.调用的时候都需要将fd从用户态拷贝到内核态,涉及到用户到内核态的切换,并且说如果fd比较大的时候是需要一定的开销,
    2.返回就绪事件的时候,poll和select是不知道具体是哪个fd事件就绪的,需要进行一个O(n)的遍历
    在这里插入图片描述
    在这里插入图片描述
  • epoll:

epoll主要有三个函数,epoll_create(int size),创建一个epoll,size是epoll想要监听的文件符的数量,返回值就是epoll对应的文件描述符,后面我们可以通过返回的文件描述符来操作我们这个epoll。
第二个函数就是epoll_ctl,就是对我们创建的epoll进行操作。
epoll创建之后,底层内核空间是一个eventpoll,有三个元素,等待队列、就绪队列、红黑树
红黑树的话就是把想要监听的这些文件描述符通过红黑树的形式存储起来,通过红黑树进行高效的新增、删除、查询,
就绪列表:就是说如果有一些fd对应的socket已经是就绪的,就是数据已经到来了,这个时候就要把对应的fd添加到就序列表来,可以很快的知道就绪队列
等待队列:当我们调用的时候发现没有事件就绪,这个时候,我们就将我们的进程进行阻塞,阻塞的时候我们就会把这个进程关联到我们的这个等待队列里面,以便后续有事件到来的时候唤醒我们的进程。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过在内核空间维护一个fd的红黑树(将文件描述符维护到内核态去,这样就不需要每次将我们想要监听的fd拷贝到内核态)和一个就绪链表(poll和select返回的时就绪的文件描述符),解决了poll和select的问题。


http://www.ppmy.cn/news/70182.html

相关文章

聚观早报 | 小冰启动GPT克隆人计划;ofo创始人在美创业改做咖啡

今日要闻:小冰启动“GPT克隆人计划”;ofo创始人在美创业改做咖啡;OpenAI正准备新的开源AI模型;青年失业率首破20%创新高;微软收购动视暴雪获批 小冰启动“GPT克隆人计划” 5 月 16 日,小冰公司…

如何使用Truffle来对智能合约实现并部署?

Truffle是一个广受欢迎的以太坊智能合约开发框架,支持快速构建、测试以及发布智能合约,本文将介绍使用Truffle框架实现一个完整的智能合约的步骤详情和具体代码实现。 步骤详情: 安装Truffle框架并创建项目 首先需要在本地安装Truffle框架&…

企业数字化转型背景下,低代码成为降本增效的“杀手锏”

摘要 在当今数字化时代,企业面临着加快数字化转型的巨大压力。为了降低成本、提高效率并推动创新,许多企业开始采用低代码开发平台作为其数字化转型的核心工具。本文将探讨低代码开发在企业数字化转型中的重要作用,并阐述其如何成为降本增效的…

企业级架构设计原则(含架构管理原则、业务架构设计原则、应用架构设计原则、数据架构设计原则、技术架构设计原则)

Togaf中的架构原则是一组用于指导企业架构设计和决策的基本准则。这些原则旨在支持组织的目标、价值观和战略,并提供一致性、可持续性和可扩展性的架构方案。 Togaf中提供了一些常见的架构原则,比如:保持一致性:确保架构与组织的目…

Unity里URP项目的介绍和创建

大家好,我是阿赵,接下来会介绍一下URP的使用 一、URP的介绍 URP(Universal Render Pipeline)通用渲染管线,是Unity在2019.3版本之后推出的一种新的渲染管线。 对比起默认的渲染管线,他的使用上会产生了一些变化,包括…

【LeetCode】326. 3 的幂

326. 3 的幂&#xff08;简单&#xff09; 方法一&#xff1a;试除法 思路 我们可以先进行特殊点判断&#xff0c;n < 0 的数都不可能是 3 的幂次方。接着&#xff0c;当 n > 0 且 n 能被 3 整除 时&#xff0c;我们对其整除 3 &#xff0c;直到该条件不满足&#xff…

基于matlab的长短期神经网络的三维路径跟踪预测

目录 背影 摘要 LSTM的基本定义 LSTM实现的步骤 基于长短期神经网络LSTM的三维路径跟踪预测 MATALB代码 效果图 结果分析 展望 参考论文 背影 路径跟踪是指通过计算机算法&#xff0c;。长短期记忆模型对复杂&#xff0c;非线性运动的目标跟踪&#xff0c;解决目标跟踪困难&a…

抓取动态网页的数据的具体操作方法

抓取动态网页的数据的具体操作方法 动态网页是指在用户交互过程中&#xff0c;网页内容不断更新和变化的网页。抓取动态网页的数据需要了解以下具体操作方法&#xff1a; 使用浏览器开发者工具&#xff1a;在浏览器中打开目标网页后&#xff0c;按下F12键&#xff0c;打开开发…