IO网络模型

news/2024/12/29 20:19:19/

文章目录

    • 1、用户空间和内核态空间
    • 2、网络模型-阻塞IO
    • 3、网络模型-非阻塞IO
    • 4、网络模型-IO多路复用
    • 5、网络模型-信号驱动
    • 6、网络模型-异步IO
    • 7、对比

1、用户空间和内核态空间

服务器大多都采用Linux系统,例如:

  • ubuntu和Centos 都是Linux的发行版,发行版可以看成对linux包了一层壳,任何Linux发行版,其系统内核都是Linux。我们的应用都需要通过Linux内核与硬件交互.
  • 用户的应用,比如redis,mysql等其实是没有办法去执行访问我们操作系统的硬件的,所以我们可以通过发行版的这个壳子去访问内核,再通过内核去访问计算机硬件
    在这里插入图片描述
  • 计算机硬件包括,如cpu,内存,网卡等等,内核(通过寻址空间)可以操作硬件的,但是内核需要不同设备的驱动,有了这些驱动之后,内核就可以去对计算机硬件去进行 内存管理,文件系统的管理,进程的管理等等

进程的寻址空间划分成两部分:内核空间、用户空间

什么是寻址空间呢?我们的应用程序也好,还是内核空间也好,都是没有办法直接去物理内存的,而是通过分配一些虚拟内存映射到物理内存中

在这里插入图片描述
在linux中,他们权限分成两个等级,0和3,用户空间只能执行受限的命令(Ring3),而且不能直接调用系统资源,必须通过内核提供的接口来访问内核空间可以执行特权命令(Ring0),调用一切系统资源,所以一般情况下,用户的操作是运行在用户空间,而内核运行的数据是在内核空间的,而有的情况下,一个应用程序需要去调用一些特权资源,去调用一些内核空间的操作,所以此时他俩需要在用户态和内核态之间进行切换

很好的一个用户程序读取磁盘数据的例子:

Linux系统为了提高IO效率,会在用户空间和内核空间都加入缓冲区:

写数据时,要把用户缓冲数据拷贝到内核缓冲区,然后写入设备

读数据时,要从设备读取数据到内核缓冲区,然后拷贝到用户缓冲区

针对这个操作:我们的用户在写读数据时,会去向内核态申请,想要读取内核的数据,而内核数据要去等待驱动程序从硬件上读取数据,当从磁盘上加载到数据之后,内核会将数据写入到内核的缓冲区中,然后再将数据拷贝到用户态的buffer中,然后再返回给应用程序,整体而言,速度慢,就是这个原因,为了加速,我们希望read也好,还是wait for data也最好都不要等待,或者时间尽量的短。
在这里插入图片描述


2、网络模型-阻塞IO

阻塞IO就是两个阶段都必须阻塞等待:

用户去读取数据时,会去先发起recvform一个命令,去尝试从内核上加载数据,如果内核没有数据,那么用户就会等待,此时内核会去从硬件上读取数据,内核读取数据之后,会把数据拷贝到用户态,并且返回ok,整个过程,都是阻塞等待的,这就是阻塞IO.
在这里插入图片描述


3、网络模型-非阻塞IO

非阻塞IO的recvfrom操作会立即返回结果而不是阻塞用户进程。
在这里插入图片描述
在这里插入图片描述


4、网络模型-IO多路复用

  • 无论是阻塞IO还是非阻塞IO,用户应用在一阶段都需要调用recvfrom来获取数据,差别在于无数据时的处理方案。
  • 而在单线程情况下,只能依次处理IO事件,如果正在处理的IO事件恰好未就绪(数据不可读或不可写),线程就会被阻塞,所有IO事件都必须等待,性能自然会很差。

很好的一个例子服务员给顾客点餐分两步

  • 顾客思考要吃什么(等待数据就绪)
  • 顾客想好了,开始点餐(读取数据)

要提高效率有几种办法?

方案一:增加更多服务员(多线程
方案二:不排队,谁想好了吃什么(数据就绪了),服务员就给谁点餐(用户应用就去读取数据)

问题来了:用户进程如何知道内核中数据是否就绪呢?

FD就出现了,文件描述符(File Descriptor):简称FD,是一个从0 开始的无符号整数,用来关联Linux中的一个文件。在Linux中,一切皆文件,例如常规文件、视频、硬件设备等,当然也包括网络套接字(Socket)。

通过FD,我们的网络模型可以利用一个线程监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源

相当于一群顾客中,部分顾客想好了自己要吃什么,然后就扫码下单告诉柜台某某桌点单了,这样就避免了柜台工作人员一直什么都不做,就在等顾客点餐去了

在这里插入图片描述

  • 当用户去读取数据的时候,不再去直接调用recvfrom了,而是调用select的函数,select函数会将需要监听的数据交给内核,由内核去检查这些数据是否就绪了,如果说这个数据就绪了,就会通知应用程序数据就绪,然后来读取数据,再从内核中把数据拷贝给用户态,完成数据处理,如果N多个FD一个都没处理完,此时就进行等待。

  • 用IO复用模式,可以确保去读数据的时候,数据是一定存在的,他的效率比原来的阻塞IO和非阻塞IO性能都要高
    在这里插入图片描述
    IO多路复用是利用单个线程来同时监听多个FD,并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。不过监听FD的方式、通知的方式又有多种实现,常见的有:

  • select

  • poll

select和pool相当于是当被监听的数据准备好之后,他会把你监听的FD整个数据都发给你,你需要到整个FD中去找,哪些是处理好了的,需要通过遍历的方式,所以性能也并不是那么好

  • epoll

epoll,则相当于内核准备好了之后,他会把准备好的数据,直接发给你,咱们就省去了遍历的动作。

5、网络模型-信号驱动

信号驱动IO是与内核建立SIGIO的信号关联并设置回调,当内核有FD就绪时,会发出SIGIO信号通知用户,期间用户应用可以执行其它业务,无需阻塞等待。
在这里插入图片描述
在这里插入图片描述
当有大量IO操作时信号较多,SIGIO处理函数不能及时处理可能导致信号队列溢出,而且内核空间与用户空间的频繁信号交互性能也较低。

6、网络模型-异步IO

在这里插入图片描述

7、对比

在这里插入图片描述


参考来自黑马程序员–Redis原理篇
Redis入门到实战教程


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

相关文章

爬虫小白-如何调试列表页链接与详情链接不一样并三种方式js逆向解决AES-ECB

目录 一、网站分析二、定位监听三、熟悉AES-ECB四、调试分析五、node运行js六、Python执行js 一、网站分析 三年前的案例,我的原始文章网站 ,如图我们直接点击标题进入到详情页,链接会发生跳转,且与我们在详情看到的链接&#xf…

前端面试题 —— Vue (三)

目录 一、v-model 可以被用在自定义组件上吗?如果可以,如何使用? 二、描述下Vue自定义指令 (1)自定义指令基本内容 (2)使用场景 (3)使用案例 三、Vue是如何收集依赖…

前端请求传输token到后端的两种方式

谈谈 cookie & session & jwt - 掘金 前端在每次请求时把token放在请求头中发送给后端,目前有两种方式: 一是通过cookie的形式,即把token放在cookie中,每次浏览器会自动帮我们带过去,不需要我们自己设置。 二…

美颜SDK开发指南:优化直播人像表现

在当今社交媒体和直播平台的流行趋势下,越来越多的用户渴望在直播中展现更加自信和美丽的一面。本文将探讨美颜SDK的开发指南,介绍其优化直播人像表现的重要性以及关键的技术要点。 一、用户为什么离不开美颜? 美颜SDK作为一种集成在直播应用…

php://filter绕过死亡exit

文章目录 php://filter绕过死亡exit前言[EIS 2019]EzPOP绕过exit 参考 php://filter绕过死亡exit 前言 最近写了一道反序列化的题,其中有一个需要通过php://filter去绕过死亡exit()的小trick,这里通过一道题目来讲解 [EIS 2019]EzPOP 题目源码&#…

IT职场笔记

MySQL笔记之一致性视图与MVCC实现 一致性读视图是InnoDB在实现MVCC用到的虚拟结构,用于读提交(RC)和可重复度(RR)隔离级别的实现。 一致性视图没有物理结构,主要是在事务执行期间用来定义该事物可以看到什…

【LeetCode】解码方法(动态规划)

解码方法 题目描述算法流程编程代码代码优化 链接: 解码方法 题目描述 算法流程 编程代码 class Solution { public:int numDecodings(string s) {int n s.size();vector<int> dp(n);dp[0] s[0] ! 0;if(n 1) return dp[0];if(s[1] < 9 && s[1] > 1) d…

牛客网Verilog刷题——VL49

牛客网Verilog刷题——VL49 题目解析答案 题目 从A时钟域提取一个单时钟周期宽度脉冲&#xff0c;然后在新的时钟域B建立另一个单时钟宽度的脉冲。A时钟域的频率是B时钟域的10倍&#xff1b;A时钟域脉冲之间的间隔很大&#xff0c;无需考虑脉冲间隔太小的问题。电路的接口如下图…