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模型实战。

六、小结

通过对五种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模型两个阶段都是异步的

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

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

相关文章

复制命令COPY

copy在英文中是复制的意思,所谓复制就是原来的文件并没有任何改变,重新产生了一个内容和原来文件没有任何差别的文件。复制(copy)命令主要用于复制一个或更多个文件到指定的位置,该命令可以被用于合并文件,…

ES6-数组的解构赋值

一、数组的解构赋值的规律 - 只要等号两边的模式相同,左边的变量就会被赋予对应的值二、数组的解构赋值的例子讲解 1)简单的示例(完整的解构赋值) 示例 //基本的模式匹配 // a,b,c依次和1,2&#xff0c…

Element UI+Spring Boot进行CRUD的实例

ElementUI安装与使用指南 前端代码:点击查看learnelementuispringboot项目源码 后端代码:点击查看 LearnElementUiAndSpringBoot 一、前端配置 安装axios Gitee的axios介绍与使用 GitHub的axios介绍与使用 方式一:使用npm安装 $ npm in…

深度学习(生成式模型)—— Consistency Models

文章目录 前言预备知识:SDE与ODEMethod实验结果 前言 Diffusion model需要多次推断才能生成最终的图像,这将耗费大量的计算资源。前几篇博客我们已经介绍了加速Diffusion model生成图像速率的DDIM和Stable Diffusion,本节将介绍最近大火的Co…

力扣热门100题刷题笔记 - 5.最长回文子串

力扣热门100题 - 5.最长回文子串 题目链接:5. 最长回文子串 题目描述: 给你一个字符串 s,找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。示例: 输入:s "…

【DDD】学习笔记-数据设计模型

通过分析活动获得的数据项模型,可以认为是数据分析模型,它确定了系统的主要数据表、关系及表的主要属性。到了建模的设计活动,就可以继续细化数据项模型这个分析模型,例如丰富每个表的列属性,或者确定数据表的主键与外…

从零开始手写mmo游戏从框架到爆炸(二)— 核心组件抽离与工厂模式创建

上一章我们已经完成了一个基本netty的通信,但是netty的启动很多代码都是重复的,所以我们使用工厂模式来生成不同的ServerBootstrap。 首先创建一个新的组件core组件,和common组件,主要用于netty通信和工具类,从server…

[Android] 240204批量生成联系人,短信,通话记录的APK

平常在做测试的时候,需要批量生成很多测试数据; 陌生人 联系人名字的生成支持随机生成,也可以自定义生成,自定义生成陌生人的数据,联系人的名字是否带索引; 通话记录 随机生成通话记录,在生…

在vscode上传项目到gitee

一、在Gitee上新建一个仓库 Tip:若已经创建过了,直接跳到第二部分看VsCode如何上传代码到Gitee 创建仓库比较简单,下面两张图就是整个过程,这里不在赘述,具体如下: 二、VsCode连接Gitee上创建的仓…

AtCoder Regular Contest 171(A~B)

A - No Attacking N*N棋盘上,放A个rook棋和B个pawn棋。 条件1:假设(i,j)上有一个rook,那么这 i 行和这 j 列,都不能再有其他棋子。 条件2:假设(i,j&#x…

Cadence——输出文件部分

本文章基于凡亿教育基础入门66讲 (一)MARK点,工艺边,阻抗说明相关准备文件 (1)MARK点 a,点击设置,用户偏好设置 b,指定MARK焊盘路径和封装路径 c,点击放置,手动 d,点击高级设置,将…

什么是TCP三次握手、四次挥手?

🎬作者简介:大家好,我是小徐🥇☁️博客首页:CSDN主页小徐的博客🌄每日一句:好学而不勤非真好学者 📜 欢迎大家关注! ❤️ 1、三次握手 你(客户端)给一个朋友(服务器)打电…

文心一言 VS 讯飞星火 VS chatgpt (194)-- 算法导论14.3 2题

二、用go语言,改写 INTERVAL-SEARCH 的代码,使得当所有区间都是开区间时,它也能正确地工作。 文心一言,代码正常运行: 在Go语言中,处理开区间(open intervals)时,我们需…

034 多维数组

二维数组理解图例 示例 int[][][] nums new int[2][2][2]; Random random new Random(); for (int[][] num : nums) {for (int[] ints : num) {for (int i 0; i < ints.length; i) {// 生成100以内的随机数ints[i] random.nextInt(100);}} } for (int[][] num : nums)…

Bard 最新更新:全球开放访问Gemini Pro并生成图片

深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领域的领跑者。点击订阅&#xff0c;与未来同行&#xff01; 订阅&#xff1a;https://rengongzhineng.io/ 。 今…

[嵌入式AI从0开始到入土]5_炼丹炉的搭建(基于wsl2_Ubuntu22.04)

[嵌入式AI从0开始到入土]嵌入式AI系列教程 注&#xff1a;等我摸完鱼再把链接补上 可以关注我的B站号工具人呵呵的个人空间&#xff0c;后期会考虑出视频教程&#xff0c;务必催更&#xff0c;以防我变身鸽王。 第一章 昇腾Altas 200 DK上手 第二章 下载昇腾案例并运行 第三章…

【5G SA流程】5G SA下终端完整注册流程介绍

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。 博客内容主要围绕: 5G/6G协议讲解 …

JVM工作原理与实战(三十五):性能调优

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、性能调优 1.性能调优方法 二、性能调优案例 案例1&#xff1a;解决CPU占用率高问题的方案 案例2&#xff1a;接口响应时间长问题 案例3&#xff1a;定位底层性能问题 案例4&a…

echarts使用之地图(五)

1 基本使用 百度地图 API : 使用百度地图的 api , 它能够在线联网展示地图 , 百度地图需要申请 ak 矢量地图 : 可以离线展示地图 , 需要开发者准备矢量地图数据。本文使用该方式。 json格式的数据如下&#xff1a; 格式参照&#xff1a;GeoJSON <!DOCTYPE html&…

车载充电器(OBC)氮化镓(GaN)驱动(高压高功率)设计(第四篇)

上图来自于网络 1、GaN FET概念 GaN FET&#xff0c;全称为Gallium Nitride Field-Effect Transistor&#xff08;氮化镓场效应晶体管&#xff09;&#xff0c;是一种采用氮化镓&#xff08;Gallium Nitride, GaN&#xff09;材料制作的新型功率半导体器件。相较于传统的硅基…