Unix五种I/O模型(阻塞、非阻塞、多路复用、信号驱动、异步)

文章目录

    • 概要
    • 一、I/O基础
    • 二、阻塞式I/O
    • 三、非阻塞式I/O
    • 三、I/O多路复用
    • 四、信号驱动I/O
    • 五、异步I/O
    • 六、小结

概要

在工作中,经常使用Nginx、Redis等开源组件,常提到其高性能的原因是网络I/O的实现是基于epoll(多路复用)。这次呢就基于Unix网络编程卷1的第6章【I/O复用:select和poll函数】,总结下Unix五种I/O模型(阻塞、非阻塞、多路复用、信号驱动、异步)。

一、I/O基础

我们在Linux下进行网络编写时,一般是通过Glibc库的Socket API(socket、bind、listen、accept、read、write、connect、close等API)来完成的,如下图:
socket编程
这只是表面的使用,那socket之下的OSI五层模型是如何体现的呢?见下图:
OSI五层模型具体表现

二、阻塞式I/O

阻塞式I/O是最基本的I/O模型,很好理解,就是每次系统调用(以read、waite API为例)时,如果此时不可读或写,那么调用会被阻塞,让后进程被挂起,直到内核通知进程可读或可写时,进程被唤醒,进行读写操作。
如下图:
Unix阻塞式I/O模型
ps:以recvfrom函数作为系统调用的代表,其他章节也如此。
阻塞式I/O实战(多进程模型)

三、非阻塞式I/O

非阻塞式I/O模型如下图:
Unix非阻塞式I/O模型
可以明显感觉到阻塞是I/O模型很低效,于是非阻塞式I/O模型诞生了,其进行系统调用(以read、waite API为例)时,如果此时不可读或写,那么就返回一个错误码(EAGAIN或EWOULDBLOCK),而不是阻塞当前进程,这样进程可以处理其他任务后再进行系统调用。
非阻塞式I/O模型实战。

三、I/O多路复用

不管是阻塞I/O还是非阻塞I/O,其同一时刻只能以一个客户端建立连接,如果要同时与多个客户端维持连接,即管理多个socket连接,分化出了两种编程模型:

  • 1)多线程或进程;
  • 2)通过数组等方式保存socket fd,不断轮询;
    在没有多路复用之前,实现与多个客户端维持连接的传统方法是多线程或进程,但是起一个子线程或进程的系统开销过大,所以可同时维持的客户端连接数量非常有限。

之所以传统维持多个客户端连接不常用第二种方式,主要是实现过于复杂,由于社会发展,基于阻塞or非阻塞模型的多进程/线程技术不足以支撑如此多的客户端,于是引入了I/O多路复用,即第二种方式来管理多个socket连接。

I/O多路复用解释如下:
多路:多个socket连接(即多个客户端连接);
复用:允许内核监听多个socket描述符,一旦发现进程指定的一个或多个I/O事件就绪(TCP三次握手成功、可读,可写),就通知该进程。

其模型图如下:
Unix I/O多路复用模型
I/O多路复用的API依次有三个select、poll、epoll。其中epoll性能最高,往往与Reactor编程模式结合,是目前常用的高效搭配模式。
select实战;
poll实战;
epoll实战。

本人研究Redis相关源码时,观察到其在Linux下就是通过epoll+非阻塞I/O+Reactor组合来处理I/O事件,是搞起高性能的一个关键点。

四、信号驱动I/O

信号驱动IO模型,顾名思义,其是通过信号来完成的,即当socket描述符准备就绪时,内核发送SIGIO通知进程。
Unix信号驱动模型
信号驱动IO模型实战。

这种模型的优势在于等待socket就绪期间进程不会被阻塞,主循环依旧可以执行,只需关注来自信号函数的通知即可。但是该模型在实际项目中很少使用,了解理解即可。

五、异步I/O

异步I/O由POSIX规范定义。一般来说其工作机制:告知内核启动某个动作,并让内核将整个动作(包括将数据从内核复制到用户缓冲区)完成后通知进程。

该机制与信号驱动I/O模型的区别是:信号驱动I/O模型是由内核通知进程何时可以开始一个I/O操作,但异步I/O是由内核通知进程I/O操作何时完成。

Unix异步I/O模型
进程调用系统函数aio_read(POSIX规范下异步I/O函数以aio_或lio_开头)之后,无论内核数据是否准备好,都会立即,然后进程可以去做别的事情。内核会自动处理I/O数据,并将内核直接复制数据给进程,然后向进程发送信号,进程收到信号后直接处理数据即可。

异步I/O模型是最理想的模型,但是自诞生之日起的具体实现方式(glibc aio、libaio、libeio…)就有这样或那样的缺点,2019 年 Linux 5.1 内核首次引入的高性能 异步 I/O 框架io_uring ,能显著加速 I/O 密集型应用的性能,并且使用简单,适应度广,足够稳定,但诞生的太晚了,远没有epoll应用的范围广。

异步I/O模型实战。

六、小结

通过对五种I/O模型的描述,可以发现前四种模型的区别主要在于第一阶段的处理方式(阻塞I/O和多路复用是阻塞的,非阻塞I/O【轮询】和信号驱动【通知】是非阻塞的),第二阶段形同:将数据从内核区复制到用户区,都进程都会阻塞于recvfrom函数。但异步I/O的两个阶段内核都帮我们做了,这与前四种模型是截然不同的。

五种I/O模型比较如下:
Unix五种I/O模型比较
最后聊一下阻塞、非阻塞、同步、异步在Unix网络编程语境下的概念:
阻塞:指调用结果返回之前,当前进程会被挂起,只有得到结果之后才会返回。

非阻塞:指如果不能立刻得到结果,当前进程不会被挂起。Unix下是通过立即返回规定错误码来实现的。

同步:I/O操作会阻塞当前进程,直至操作完成。由此可知前四种模型都是同步的(非阻塞I/O如果有数据时依旧需等待数据从内核区复制到用户区,或阻塞当前进程)。

异步:I/O操作不会阻塞当前进程。

我们可以举这样一个场景,小明要喝开水,客厅有其他事情,而烧水壶在卧室。

小明打开热水壶,站在热水壶面前一直等待水开 => 阻塞
小明打开热水壶后回到客厅做其他事情,一会去卧室检查一下水是否烧开,烧开再使用 => 非阻塞
小明觉得一会去卧室检查一下太费劲了,于是换了一个水开报警的热水壶:
现在小明打开热水壶后回到客厅做其他事情,等到热水壶报警再去卧室用水 => 异步

ps:我们举的场景只有一个阶段,而Unix五种I/O模型是有两个阶段的【第一阶段获取I/O就绪事件,第二阶段将I/O数据从内核区复制到用户区】,只有异步I/O模型两个阶段都是异步的

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

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

相关文章

护眼灯的色温标准是什么?护眼灯参数标准介绍

选择合适的护眼台灯不仅能提升家居的品质,还能为我们的生活增添一份温馨与舒适。不过有些色温调节不当不仅不能达到很好的学习效率,还容易打瞌睡,甚至伤眼睛的情况也有可能出现,那么什么色温有什么标准呢? 一、合适的…

互联网加竞赛 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…

大型语言模型(LLM)的优势、劣势和风险

最近关于大型语言模型的奇迹()已经说了很多LLMs。这些荣誉大多是当之无愧的。让 ChatGPT 描述广义相对论,你会得到一个非常好(且准确)的答案。然而,归根结底,ChatGPT 仍然是一个盲目执行其指令集…

进程控制(Linux)

进程控制 一、进程创建1. 再识fork2. 写时拷贝 二、进程终止前言——查看进程退出码1. 退出情况正常运行,结果不正确异常退出 2. 退出码strerror和errno系统中设置的错误码信息perror异常信息 3. 退出方法exit和_exit 三、进程等待1. 解决等待的三个问题2. 系统调用…

银行数据仓库体系实践(17)--数据应用之营销分析

营销是每个银行业务部门重要的工作任务,银行产品市场竞争激烈,没有好的营销体系是不可能有立足之地,特别是随着互联网金融发展,金融脱媒”已越来越普遍,数字化营销方兴未艾,银行的营销体系近些年也不断发展&#xff0c…

【精选】java继承进阶,子类继承父类(内存图、内存分析工具)

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏…

ftrace工具学习笔记

ftrace是一个功能强大的Linux内核跟踪工具,可用于分析内核的行为和性能问题。它可以用来收集各种内核跟踪数据,如函数调用、内存分配、中断处理等。以下是ftrace的一些主要特点和用法: ftrace是内核自带的跟踪工具,因此无需安装。…

FRP内网穿透如何避免SSH暴力破解(二)——指定地区允许访问

背景 上篇文章说到,出现了试图反复通过FRP的隧道,建立外网端口到内网服务器TCP链路的机器人,同时试图暴力破解ssh。这些连接造成了流量的浪费和不必要的通信开销。考虑到服务器使用者主要分布在A、B、C地区和国家,我打算对上一篇…

ELAdmin 前端启动

开发工具 官方指导的是使用WebStorm,但是本人后端开发一枚,最终还是继续使用了 idea,主打一个能用就行。 idea正式版激活方式: 访问这个查找可用链接:https://3.jetbra.in/进入任意一个能用的里面,顶部提…

消息中间件之RocketMQ源码分析(六)

Consumer消费方式 RocketMQ的消费方式包含Pull和Push两种 Pull方式。 用户主动Pull消息,自主管理位点,可以灵活地掌控消费进度和消费速度,适合流计算、消费特别耗时等特殊的消费场景。 缺点也显而易见,需要从代码层面精准地控制…

docker部署自己的网站wordpress

目录 安装 1.创建目录 2.创建并启动mysql 3.创建并启动wordpress 使用 1.设置语言 2.设置基础信息 3.首页 安装 1.创建目录 mkdir -p /opt/wordpress/{db,data} 2.创建并启动mysql docker run -d --name my_mysql --restart always -e MYSQL_ROOT_PASSWORD123456 -e …

flutter使用qr_code_scanner扫描二维码

qr_code_scanner仓库地址:qr_code_scanner | Flutter Package 需要添加android和ios的相机权限和本地相册权限: android中添加权限: 在android\app\build.gradle中修改:minSdkVersion 20 并且在android/app/src/main/AndroidManifest.xml中…

【力扣】Z字形变换,模拟+直接构造

Z字形变换原题地址 方法一:利用二维矩阵模拟 对于特殊情况,z字形变换后只有一行或只有一列,则变换后的字符串和原字符串相同。 对于一般情况,我们可以考虑按照题目要求,把字符串按照Z字形存储到二维数组中&#xff…

【linux】git和gdb调试工具

在linux下提交代码同步到gitee 1.创建一个新的仓库(演示步骤) 2.init 这两个步骤用于识别提交代码的身份,一个你的名字,一个你的邮箱 开启本地仓库 克隆本地仓库成功 我们将这个仓库拷到了111目录底下. 我们发现少了一个.gitig…

最小覆盖子串[困难]

优质博文:IT-BLOG-CN 一、题目 给你一个字符串s、一个字符串t。返回s中涵盖t所有字符的最小子串。如果s中不存在涵盖t所有字符的子串,则返回空字符串"" 。 对于t中重复字符,我们寻找的子字符串中该字符数量必须不少于t中该字符数量…

使用Nginx搭建旁路服务器获取客户端真实IP

一、前言 在实际业务开发过程中,很多时候有记录客户端真实IP的需求,但是从客户端发送的请求往往会经过很多代理服务器,导致后端服务获取的IP为代理以后的IP,不具有业务含义。为了解决这个问题,可以搭建一个旁路服务器…

谷歌seo搜索引擎优化方法有什么?

想知道谷歌优化方法有什么,首先要了解谷歌搜索引擎的工作原理,谷歌的工作原理主要是通过“爬虫”来实现的,所谓“爬虫”就是一只能够读取并分析网页内容的程序,或者也能理解成机器人,当你在谷歌上输入关键词进行搜索时…

uniapp小程序实现直播组件live-player全屏问题

实现效果&#xff1a; 代码&#xff1a; <template><view class"player-content"><!-- #ifdef APP-PLUS --><video id"myVideo" :src"srcLink" autoplay controls><!-- 打开全屏 --><image class"img…

速度规划:s形曲线------pencv c++绘图(1)

理论篇 代码篇&#xff1a; opencv环境配置 注意&#xff01;注意&#xff01;注意&#xff01; 配置结束后运行环境切换为如下再运行&#xff1a; #include <iostream> #include <cmath>#include <opencv2/opencv.hpp>using namespace std;double a_max…

github和gitee

github GitHub是一个面向开源及私有软件项目的托管平台&#xff0c;因为只支持Git作为唯一的版本库格式进行托管&#xff0c;故名GitHub。 github可以给提交的代码打上标签&#xff0c;方便版本的迭代和回退&#xff0c;也是一个存储代码的仓库 github工作区 gitee是gitHub的…