几种IO模型

部分图来自网络和黑马程序员

IO

IO分为两个阶段:数据准备(数据读取到内核缓冲区)+数据拷贝(从内核缓冲区拷贝到用户空间)

例如,在下图中两个主机的通信中,程序A/B从TCP接收缓冲区读取数据时,需要通过系统调用先将数据(如果有)读取到内核缓冲区,再拷贝到程序A/B的用户空间;发送数据同理。

上面的接收和发送数据过程中,如果数据还未到达,那程序A/B会怎么办呢?这与其采用的IO模型有关。
在这里插入图片描述

阻塞IO:进程在两阶段都会处于阻塞状态

在阻塞I/O模型中(Blocking I/O),当一个进程发起I/O操作(如读或写),它会一直等待该操作完成。在此期间,进程会被阻塞,无法执行该进程的其他任务( CPU时间切换给其他进程),直到数据可用并传输完毕。

特点:简单易用,但可能导致资源利用率低下,特别是在高并发场景下。

如,服务端监听多个socket(客户端)。当调用recvfrom从网卡获取数据时,若数据还未准备好,则服务端需要阻塞等待,在此过程中,监听的其他socket没法得到处理。

在这里插入图片描述

非阻塞IO:数据准备阶段不阻塞,数据拷贝阶段会阻塞

非阻塞I/O模式下(Non-blocking I/O),进程发起I/O操作后立即返回,无论数据是否准备好。如果数据不可用,调用会立即返回一个错误码或特殊值,进程可以继续执行其他任务,然后再次检查数据是否准备就绪。

特点:避免了线程长时间阻塞,但可能需要不断地轮询检查数据状态,导致CPU占用率偏高。

如,服务端线程监听多个socket(客户端)。当调用recvfrom从网卡获取某socket发送的数据,若数据未准备好,则服务端线程需要轮询,在此过程中,其他socket没法得到处理。

在这里插入图片描述

IO多路复用:数据拷贝阶段是阻塞的

文件描述符(File Descriptor) :简称FD,是一个从0开始递增的无符号整数,用来关联Linux中的一个文件。在Linux中,一切皆文件,例如常规文件、视频、硬件设备等,当然也包括网络套接字(Socket) 。
I0多路复用(Multiplexing I/O):允许单个进程监视多个描述符(文件描述符、套接字等),等待其中任何一个变为可读、可写状态。这意味着进程可以同时等待多个I/O事件,而无需为每个描述符单独阻塞。

服务端进程调用监听函数(select、epoll等)同时监听多个socket,并等待数据(阻塞等或非阻塞都可以,取决于给定的超时时间)。当一个或多个被监听的socket就绪,则返回readable。然后反复调用recvfrom从网卡获取那些就绪的socket发送的数据。

即相比之前的逐个等待socket的方式,IO多路复用可以集体等待,且专心处理有事件的socket,把时间花在刀刃上。

在这里插入图片描述

在这里插入图片描述

select

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout)。用于实现I/O多路复用,它允许一个进程同时监控多个文件描述符(如套接字、管道、终端等)的可读、可写或异常状态。

在这里插入图片描述

在这里插入图片描述

不足:

  • 有上限。最多监听1024个fd(猜测,且fd最大值为1023?因为数组只有1024个bit)
  • 两次拷贝。需要将要监听的fd_set拷贝到内核,select结束后,又要从内核中拷贝回来
  • 两次遍历。内核中需要遍历一次以设置就绪状态,用户空间中需要遍历一次,以判断哪个fd已就绪

poll

在这里插入图片描述

在这里插入图片描述

与select对比:
select模式中的fd_ set大小固定为1024, 而pollfd在内核中采用链表,理论上无上限,但

  • 还是需要两次拷贝和两次遍历。
  • 监听FD越多,每次遍历消耗时间也越久,性能反而会下降。

epoll

相较于selectpoll有着显著的性能优势。epoll通过维护一个内部文件描述符集合并使用事件驱动的方式工作,仅关注实际活跃的连接,从而大大减少了在高并发环境下所需的系统调用次数和上下文切换。

epoll主要涉及以下三个系统调用:

  1. epoll_create(): 在内核中创建一个epoll文件描述符,用于跟踪感兴趣的文件描述符集合。

    int epoll_create(int size);
    
    • size 参数在现代Linux内核中被忽略,但通常传入1作为占位符。

    在这里插入图片描述

  2. epoll_ctl(): 控制epoll文件描述符,可以添加、修改或删除对特定文件描述符的监听事件。并且是使用红黑树来管理监听的socket,增删改查时间复杂度是 O(logn)

    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
    
    • epfd: 由epoll_create返回的文件描述符。
    • op: 操作类型,如EPOLL_CTL_ADD(添加)、EPOLL_CTL_MOD(修改)、EPOLL_CTL_DEL(删除)。
    • fd: 要监听的文件描述符。
    • event: 一个epoll_event结构体,包含要监听的事件类型(如EPOLLIN, EPOLLOUT)和用户数据指针。事件触发就加入就绪链表,事件驱动。

    在这里插入图片描述

    epoll_event 结构体

    struct epoll_event {
        uint32_t events;      /* Epoll events */
        epoll_data_t data;    /* User data variable */
    };
    
    • events: 位掩码,表示关注的事件类型。
    • data: 用户自定义数据,可以存储指向结构体或其他数据的指针,以便在事件触发时使用。
  3. epoll_wait(): 等待一个或多个epoll事件的发生,当任何注册的事件准备就绪时返回。

    int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
    
    • epfd: 同上。
    • events: 用于接收就绪事件的数组。
    • maxevents: 该数组能容纳的最大事件数。
    • timeout: 等待超时时间,单位为毫秒,与select类似。

    在这里插入图片描述

总体结构:

在这里插入图片描述

优势:

  • 红黑树效率高。基于epoll实例中的红黑树保存要监听的FD,理论上无上限,而且增删改查效率都非常高,性能不会随监听的FD数量增多而下降。
  • 一次添加,无需拷贝。每个FD只需要执行一次epoll_ctl添加到红黑树,以后每次epol_wait无需传递任何参数,无需重复拷贝FD到内核空间。
  • 一次拷贝(且不是全部拷贝),且无需遍历。内核会将就绪链表中的FD直接拷贝到用户空间的指定位置,用户进程无需遍历就能得到就绪的FD
epoll的触发模式

当FD有数据可读时,我们调用epoll_wait就可以得到通知。但是事件通知的模式有两种:

  1. Level Triggered: 水平触发,简称LT。当FD有数据可读时,会重复通知多次,直至数据处理完成。是Epoll的默认模式,select/poll 只有水平触发模式。
  2. Edge Triggered: 垂直触发,简称ET。当FD有数据可读时,只会被通知一次,不管数据是否处理完成。

就绪节点拷贝到用户空间前,会将其从就绪链表中断开,拷贝完后,再根据触发模式采取动作。

  • LT模式中,内核会将其重新加入就绪链表,所以后续还会触发epoll_wait

    1. 重复通知、重复读对效率有影响
    2. 惊群。多个进程监听了同一个socket,他就绪时,所有进程都会被通知(唤醒),然而通常只有一两个进程获得了该事件,并进行处理;其他进程在发现获取事件失败后,又继续进入了等待状态;然后再次被唤醒,循环往复。这在一定程度上降低了系统性能。
  • ET模式,内核会将其直接删除

    1. 需要自己手动将就绪节点添加回去
    2. 或手动把数据一次读完。要使用非阻塞地读,防止读不到数据时阻塞进程。

一般来说,边缘触发的效率比水平触发的效率要高,因为边缘触发可以减少 epoll_wait 系统调用的次数。

IO多路复用-web流程

在这里插入图片描述

异步IO

异步I/O(Asynchronous I/O,简称AIO)是一种I/O处理模式,它允许应用程序发起一个或多个I/O操作后立即返回,继续执行后续代码,而无需等待I/O操作完成。当I/O操作实际完成时,系统会通过预先设定的机制(如回调函数、事件通知、信号等)通知应用程序,从而实现非阻塞的并发处理。

简单来说,发起一个IO操作后直接返回执行其他代码,等到IO(数据准备+数据拷贝)完成后,会收到通知,再去处理。

在这里插入图片描述

  • 应用程序在发起I/O操作后不会被阻塞,提高了程序的响应性和并发能力。
  • 因为程序无需等待I/O操作,CPU可以处理其他任务,提高了整体系统吞吐量。
  • 异步I/O编程模型相对同步I/O更加复杂,需要处理回调逻辑和潜在的并发问题。

信号驱动IO

信号驱动I/O(Signal-Driven I/O)结合了信号(signals)机制与I/O操作,实现非阻塞式的输入输出处理。这种模型允许应用程序在有数据可读或可写时通过信号的形式得到通知,而无需主动轮询或阻塞等待。

  1. 注册信号处理器:首先,应用程序需要注册一个信号处理器(signal handler),这个处理器专门用于处理特定的信号,比如SIGIO。这个信号会在相关的I/O事件(如数据可读或可写)发生时被发送给进程。
  2. 等待信号:应用程序继续执行其他任务,不再直接等待I/O操作完成。当I/O事件发生时,内核会发送一个信号(通常是SIGIO)给进程,而不是让进程阻塞。
  3. 信号处理器响应:应用程序中的信号处理器被调用,它通常会快速处理信号,然后通过某种方式(如设置一个标志或者将任务加入到事件队列)通知主循环,表明有I/O操作就绪,需要进一步处理。

在这里插入图片描述

  • 优点:信号驱动I/O避免了持续轮询的开销,同时也避免了在selectpoll调用中等待的阻塞,提高了程序的响应性。
  • 局限:信号处理函数的执行受到限制,不能执行复杂的操作,且信号处理过程中应当尽量快速完成,因为它会中断正常的程序执行流。此外,信号是全局的,可能与其他信号处理逻辑冲突,增加了编程的复杂性。

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

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

相关文章

Vue3实战笔记(13)—pinia安装笔记

文章目录 前言安装和配置pinia总结 前言 Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。 Pinia是一个轻量级的状态管理库,它专注于提供一个简单的API来管理应用程序的状态。相比之下,Vuex是一个更完整的状态管理库&#xf…

视频模糊变清晰,这13个工具总有一个能帮到你,收藏好

1、Topaz Video Enhance AI 这是一款非常专业的视频分辨率放大软件,使用来自多个帧的信息来实现视频升级、去噪、去隔行扫描和恢复的结果。 Topaz Video Enhance AI可以将视频放大和增强8K分辨率的镜头,并提供真实的细节和动作一致性。它采用AI技术实现…

【STM32HAL库】DAC输出0-3.3v

一、简要介绍一下DAC DAC也有分辨率,转换时间,精度等 分辨率常见为8或12位的 转换时间F1,F4,F7都是3us左右,而H7系列是1.7us 1.DAC框图 2.数据格式(对齐方式) 3.触发源 4.可以发送DMA请求 注意&#xff…

OSS证书自动续签,一分钟轻松搞定,解决阿里云SSL免费证书每3个月失效问题

文章目录 一、🔥httpsok-v1.11.0支持OSS证书自动部署介绍支持特点 二、废话不多说上教程:1、场景2、实战Stage 1:ssh登录阿里云 ECSStage 2:进入nginx (docker)容器Stage 3:执行如下指令Stage 3…

vivado Virtex UltraScale 配置存储器器件

Virtex UltraScale 配置存储器器件 下表所示闪存器件支持通过 Vivado 软件对 Virtex UltraScale ™ 器件执行擦除、空白检查、编程和验证等配置操作。 本附录中的表格所列赛灵思系列非易失性存储器将不断保持更新 , 并支持通过 Vivado 软件对其中所列非易失…

Flink HA模式下JobManager切换时发送告警

资源&版本信息 Flink版本1.14.6 运行平台:K8s HA使用ZK(使用K8s的ETC应该是一个道理) 详解Flink HA原理 Flink启动时会创建HighAvailabilityServices提供HA和相关基础服务,其中包括leaderRetrievalService和LeaderElecti…

MP4视频转gif怎么做?看看这篇就会了

喜欢刷短视频的小伙伴经常会看到各种好玩有趣的片段,想要通过自己将这段视频制作成gif动态图片的还不想下载软件的时候要怎么办呢?这个很简单,不需要下载什么软件用专业的Gif动画制作网站,支持超清的画质导出,能够完成…

ssm123基于java web的网上书城系统的设计与实现+vue

基于java web的网上书城系统的设计与实现vue 摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势,商品交易当然也不能排除在外,随着商品交易管理的不断成熟,它彻底改变了…

Git详解之六:Git工具

现在,你已经学习了管理或者维护 Git 仓库,实现代码控制所需的大多数日常命令和工作流程。你已经完成了跟踪和提交文件的基本任务,并且发挥了暂存区和轻量级的特性分支及合并的威力。 接下来你将领略到一些 Git 可以实现的非常强大的功能&…

Java抽象类:为何它是你代码架构的基石?

目录 1、抽象类的概念 2、抽象类语法 3、抽象类特性 4、抽象类的作用 5、 完结散花 个人主页:秋风起,再归来~ 文章专栏:javaSE的修炼之路 个人格言:悟已往之不谏,知来者犹可追 克…

WWW服务器搭建(2)——Apache服务器配置与管理

一、Apache简介 1.1 关于Apache Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的Web服务器,可以在大多数计算机操作系统中运行,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。…

【Linux 系统】多线程(生产者消费者模型、线程池、STL+智能指针与线程安全、读者写者问题)-- 详解

一、生产者消费者模型(重点) 如图,在生活中,学生就是消费者角色,工厂是真正的生产者角色,那么超市是什么呢?为什么需要超市?超市是交易场所。我们的家附近不一定有工厂,而…

JumpServer发布web应用

项目背景: 由于防火墙密码安全没有达到审计要求,需要加固防火墙用户安全,通过JumpServer发布防火墙登录页面,提供远程访问 认证要求: 1、密码记忆多次 2、密码大小写 3、密码字符 4、密码数字 加固前密码策略&…

【C++要哮着学】初识C++,什么是C++?什么是命名空间?什么又是缺省函数?

文章目录 前言1、C简介1.1、什么是C1.2、C起源1.3、C发展 2、C关键字(C98)3、命名空间3.1、命名空间的定义及使用3.2、命名空间的嵌套3.3、命名空间的三种使用方式3.3.1、加命名空间名称及作用域限定符3.3.2、使用using将命名空间中某个成员引入3.3.3、使…

上位机图像处理和嵌入式模块部署(树莓派4b 应用的注意事项)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 树莓派系列开发板最早的时候,价格还是比较高的。不过由于它生态比较丰富,使用起来比较方便,所以大家都默认了它…

UE4_照亮环境_不同雾效的动态切换

一、问题及思路: 我们在一个地图上,经常切换不同的区域,不同的区域可能需要不同的色调,例如暖色调的野外或者幽暗的山洞,这两种环境上,雾效的选用肯定不一样,夕阳西下的户外用的就是偏暖的色调&…

如何用微信小程序实现远程控制4路控制器/断路器

如何用微信小程序实现远程控制4路控制器/断路器呢? 本文描述了使用微信小程序调用HTTP接口,实现控制4路控制器/断路器,支持4路输出,均可独立控制,可接入各种电器。 可选用产品:可根据实际场景需求&#xf…

【命名空间】(中北大学-程序设计基础(2))

目录 题目 源码 结果示例 题目 学校的人事部门保存了有关学生的部分数据(学号、姓名、年龄、住址),教务部门也保存了学生的另外一些部分数据(学号、姓名、性别、成绩),两个部门分别编写了本部门的数据管…

化学式的分子量计算——字符转数字

【题目描述】 给出一种物质的分子式(不带括号),求分子量。本题中的分子式只包含4种原子,分别为C, H, O, N,原子量分别为12.01, 1.008, 16.00, 14.01(单位:g/mol)。例如,…

Shell的运行原理和Linux的权限

Shell的运行原理 Linux严格意义上说是一个操作系统,我们称之为“核心(kernel)”,但我们一般用户不能直接使用kernel,而是通过kernel的“外壳程序”,也就是所谓的Shell,来与kernel沟通。 Shell…