【IO】IO模型与零拷贝

前言:

        正在运行的程序其实就是系统中的一个进程,操作系统会为每一个进程分配内存空间,而内存空间分为两部分,一部分是用户空间,这是用户进程访问的内存区域;另一部分是内核空间,是操作系统内核访问的内存区域。

        如网络、磁盘IO等操作,出于安全性考虑,用户进程不能直接与外部设备进行数据交互,用户进程只能向操作系统发起IO调用请求,由操作系统内核与外部设备进行数据交互,完成真正的IO操作。

IO模型:

        首先明确一个概念,磁盘、socket通讯的网卡等都属于外部设备。我们经常看到的输入(input)输出(output)等概念其实就是指用户进程与这些外部设备的交互。

IO实质

        输入(input)将外部设备中的数据加载到用户进程内。

        输出(output)将用户进程内的数据迁移到外部设备。

一个完整的IO过程分为几步?

        1、用户进程向操作系统发起IO调用请求。

        2、操作系统准备数据,将外部设备中的数据加载到内核缓冲区。

        3、操作系统拷贝数据,将内核缓冲区的数据拷贝到用户进程缓冲区。

在一次完整IO过程中,根据用户进程的不同表现形式,我们可以将IO模型分成以下几种:

        (1)阻塞IO(Blocking IO)

        表现:从发起IO调用请求(recvrom系统函数调用)至接收到操作系统内核拷贝来的数据的整个过程中,用户进程一直处于阻塞状态。

        (2)非阻塞IO(Non-Blocking IO)

        表现:用户进程发起IO调用请求后,如果数据还未准备好,内核会直接返回错误信息,结束用户进程的阻塞状态,用户进程不断轮询发起IO调用请求,直至数据准备就绪。

        特点:不像BIO,用户进程在整个IO流程中都是阻塞的,通过轮询发起IO请求来获取数据。相较于BIO有性能提升,但在数据准备好之前,用户进程会不断调用系统函数,占用大量的CPU资源。

        (3)IO多路复用

        表现:用户进程调用系统函数select后,可以监控多个fd,只要有任意一个fd的数据准备就绪,select函数就会返回可读提示给用户进程,此时进程再调用recvfrom系统函数读取数据。

        特点:解决了NIO频繁的系统调用问题,减少CPU资源的消耗。只有在监视的fd返回可读提升后,用户进程才会调用recvfrom函数,请求获取数据。

        fd概念

        1、文件描述符全称File Description,是一个从0开始的无符号整数,每个fd都可以关联一个文件。

        2、在linux中,万物皆文件,常规文件、视频、硬件设备、socket等都可以用一个fd来进行关联。

        简单提一下,IO多路复用模型涉及到的系统函数有三个:selectpollepoll

        select函数特点有连接数限制,一次最多只能监听1024个fd;select函数返回可读提示后,用户进程需要遍历fd集合才能得知哪个fd数据准备就绪(时间复杂度O(n))。

        poll函数特点解决了select函数有连接数限制的问题,但还是需要遍历fd集合。

        epoll函数特点既解决了连接数限制问题,又无需遍历fd集合获取,可以用O(1)的时间复杂度获取可读的fd。   

        (4)异步(Asynchronous IO)

        表现:用户进程发起IO调用请求后,内核直接返回提示信息,在随后的数据准备阶段以及数据拷贝阶段,用户进程不会阻塞;在数据拷贝操作完成后,内核发送信号通知用户进程。

        特点:无论是NIO模型还是IO多路复用模型,它们都会在数据拷贝阶段:将数据从内核缓冲区拷贝到用户缓冲区阻塞,而AIO模型实现了真正的IO全过程无阻塞。

零拷贝:

        服务端一般都会提供文件下载功能,这个功能的实质是:基于与客户端建立的socket连接,将服务器磁盘上的文件发送到客户端主机的网卡上。

        文件下载功能大概的IO流程:

从磁盘中读取数据到应用程序内存

        1、用户进程调用read函数,向操作系统发起IO请求,上下文从用户态切换为内核态。

        2、DMA控制器将数据从磁盘控制缓冲区中拷贝到内核缓冲区。

        3、CPU再把内核缓冲区的数据,拷贝到用户缓冲区,上下文从内核态切换为用户态,read函数返回。

将应用程序内存中的数据写入到socket

        4、用户进程调用write函数,发起IO调用请求,上下文从用户态切换为内核态。

        5、CPU将用户缓冲区中的数据,拷贝到socket缓冲区。

        6、DMA控制器再将数据从socket缓冲区,拷贝到网卡设备,上下文从内核态切换回用户态,write函数返回。

        如上图所示,整个过程包含4次上下文切换(用户态、内核态转换)、4次数据拷贝操作,效率较低。看到这里,可能大家会对DMA有疑惑,它是什么?有什么用?

        DMA:全称Direct Memory Access,直接内存访问,本质上是一块主板上独立的芯片。它的作用是替代CPU完成与IO设备的数据传输工作,减少CPU的负担,提高CPU的利用效率。

        读取磁盘文件的完整IO流程:

        1、用户进程调用read函数,发起IO调用请求。

        2、CPU收到指令后,对DMA控制器发起指令调度。

        3、DMA收到IO请求(CPU指令调度)后,请求获取磁盘数据。

        4、磁盘将数据放入磁盘控制缓冲区,通知DMA控制器。

        5、DMA将数据从磁盘控制缓冲区拷贝到内核缓冲区。

        6、DMA通知CPU,CPU负责将数据从内核缓冲区拷贝到用户缓冲区。

        7、用户应用进程从内核态切换回用户态。

        通过读取磁盘文件的IO流程,我们也不难得到将数据写出到网卡的整个IO流程。

零拷贝概念:不是指没有数据拷贝操作,而是减少上下文切换次数和数据拷贝的次数。

        零拷贝实现方案:

        (1)mmap&write使用mmap系统函数代替read系统函数。

        流程:DMA将磁盘缓冲区的数据拷贝到内核缓冲区,此时CPU不会将内核缓冲区中的数据拷贝到用户缓冲区,因为内核缓冲区内的数据会被映射到用户空间,但mmap函数返回时,还是会从内核态切换到用户态。

        特点:减少了一次数据拷贝操作,但整个IO过程还是有4次上下文切换操作。

        (2)sendfile使用sendfile系统函数代替read、write两个系统函数

        流程:DMA将磁盘缓冲区的数据拷贝到内核缓冲区,随后CPU直接将内核缓冲区内的数据拷贝到socket缓冲区中。

        特点:减少了read函数返回时的上下文的切换、write函数调用时的上下文的切换。总计减少了一次数据拷贝操作和两次上下文切换操作。

        (3)sendfile&SG-DMA

        流程:DMA将磁盘缓冲区的数据拷贝到内核缓冲区,缓冲区将文件描述符和数据长度传到 socket缓冲区,网卡的SG-DMA控制器可直接将内核缓冲区里的数据拷贝到网卡设备。

        特点:整个IO流程不涉及CPU,没有将数据从内核缓冲区拷贝到用户缓冲区这一流程,总计减少了两次数据拷贝操作和两次上下文切换操作。

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

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

相关文章

详解Keras3.0 Layer API: LSTM layer

LSTM layer 用于实现长短时记忆网络,它的主要作用是对序列数据进行建模和预测。 遗忘门(Forget Gate):根据当前输入和上一个时间步的隐藏状态,计算遗忘门的值。遗忘门的作用是控制哪些信息应该被遗忘,哪些…

vue2、vue3状态管理之vuex、pinia

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、状态管理之vuex1.1 State调用:1.2 Mutation在vuex中定义:在组件中使用: 1.3 Action在vuex中定义:将上面的减…

Vue 自定义ip地址输入组件

实现效果&#xff1a; 组件代码 <template><div class"ip-input flex flex-space-between flex-center-cz"><input type"text" v-model"value1" maxlength"3" ref"ip1" :placeholder"placeholder"…

VMware之FTP的简介以及搭建使用计算机端口的介绍

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《产品经理如何画泳道图&流程图》 ⛺️ 越努力 &#xff0c;越幸运 目录 一、FTP介绍 1、什么是FTP&#xff1a; 2、FTP适用于以下情况和应用场景&#xff1a; 3、winServer2012搭…

Verilog置换处理脚本

文章目录 一、介绍二、脚本 一、介绍 在Verilog中的置换处理&#xff0c;为将一个数据的数据位按照某种规则进行重新排列。 以DES算法的初始置换为例 初始置换将64比特的明文&#xff0c;按照初始置换表进行置换&#xff0c;得到一个乱序的64bit明文组。 初始置换表如下&…

加速计算,为何会成为 AI 时代的计算力“新宠”

随着科技的发展&#xff0c;处理大量数据和进行复杂计算的需求越来越高&#xff0c;人工智能、大数据和物联网等领域更是如此&#xff0c;传统的计算方式已经无法满足这些需求。因此&#xff0c;加速计算作为一种现代计算方式&#xff0c;成了必要的手段。加速计算具有前所未有…

为什么设计制造行业需要数据加密?

设计制造行业是一个涉及多种技术、工艺、材料和产品的广泛领域&#xff0c;它对经济和社会的发展有着重要的影响。然而&#xff0c;随着数字化、智能化和网络化的发展&#xff0c;设计制造行业也面临着越来越多的数据安全风险&#xff0c;如数据泄露、数据篡改、数据窃取等。这…

Qt Creator可视化交互界面exe快速入门4

上一期介绍了信号与槽&#xff0c;本期介绍加法计算器 我们来新建一个项目 然后拖动设置按钮 还需要个输出框 这里拖动Line Edit 我这里只是简单演示一下&#xff0c;做个低配版计算器&#xff0c;再加个加号和一个等于号就结束了。 然后回到代码编辑部分&#xff0c;我们需要…

代码随想录27期|Python|Day29|回溯算法|491.递增子序列|46.全排列|47.全排列 II

491. 非递减子序列 本题不是单纯的去重题目&#xff0c;而是需要保持数字在原数组的顺序。 比如&#xff1a;[4,5,6,7]和[4,6,5,7]相比&#xff0c;后者就不能选择[5,6,7]这个排列&#xff0c;因为违反了设置的顺序。所以去重的方法就只有哈希表。 需要在每一层设置一个哈希表…

注册谷歌企业开发者账号所需的邓白氏码是什么?如何获取?以及相关费用?

随着谷歌政策的收紧&#xff0c;谷歌对个人开发者账号发布应用的要求越来越高&#xff0c;需要20人连续测试14天&#xff0c;才能提审&#xff0c;因此很多开发者选择使用企业账号来进行上架。 而众所周知&#xff0c;注册谷歌企业开发者账号需要邓白氏码。什么是邓白氏码&…

制作系统U盘启动surface教程

最近本人是崩溃的&#xff1a;我surface pro9系统之前被我更新成win11 dev的开发预览版&#xff0c;不好用&#xff0c;有很多bug&#xff0c;升级后才发现已经是预览版成员资格&#xff0c;回退不了&#xff0c;重置初始化依然是dev预览版和取消预览计划是灰色的&#xff0c;退…

Volume Control 2

为游戏添加音乐和音效总是需要一些编码来设置一个系统来控制、显示和保存应用程序的音量设置。 音量控制的设计是为了立即为您设置这些内容,让您有更多时间专注于最重要的事情——制作出色的游戏! 在版本2中,我们对系统进行了重新设计,使其更加模块化、灵活,甚至更易于使用…

MySQL——索引

目录 一.没有索引&#xff0c;可能会有什么问题 二.MySQL与存储 1.先来研究一下磁盘 2.MySQL与磁盘交互基本单位 3.建立共识与总结 三.索引的理解 三.索引操作 1.创建主键索引 2.唯一索引的创建 3.普通索引的创建 4.全文索引的创建 四.查询索引 五.删除索引 一…

MySQL进阶SQL语句

1、select 显示表格种一个或数个字段的所有数据记录 语法&#xff1a;select "字段" from "表名"; 2、distinct 不显示重复的数据记录 语法&#xff1a;select distinct "字段" from "表名"; 3、where 有条件查询 语法&#x…

模式识别与机器学习-SVM(核方法)

SVM&#xff08;核方法&#xff09; 核方法核技巧在SVM中的应用 谨以此博客作为复习期间的记录 核方法 对解线性分类问题&#xff0c;线性分类支持向量机是一种非常有效的方法&#xff0e;但是&#xff0c;有时分类问题是非线性的&#xff0c;这时可以使用非线性支持向量机&a…

线程池原理及使用

线程池继承关系 1.为什么使用线程池&#xff1f; 1.反复创建线程开销大; 2.过多线程会占用太多内存(执行任务易出现“内存溢出”); 3.加快程序响应速度; 4.合理利用CPU和内存; 5.统一管理线程; 2.创建和停止线程池 2.1.线程池参数解释 1.keppAliveTime 如果线程池当中的线程数…

使用Python构建令人瞩目的高频交易算法

大家好&#xff0c;在金融领域&#xff0c;高频交易&#xff08;HFT&#xff09;因其能够以极高的速度执行大量订单的能力而备受关注。高频交易算法旨在识别并利用不同市场间的微小价格差异&#xff0c;因此交易者需要实现低延迟系统来进行套利策略&#xff0c;本文将探索使用P…

我的NPI项目之Android系统升级 - 同平台多产品的OTA

因为公司业务中涉及的面比较广泛&#xff0c;虽然都是提供移动终端PDA&#xff0c;但是使用的场景很多时候是不同的。例如&#xff0c;有提供给大型物流仓储的设备&#xff0c;对这样的设备必需具备扫码功能&#xff0c;键盘&#xff08;戴手套操作&#xff09;&#xff0c;耐用…

大数据求职心得

........................................................................................................................................................... 大数据求职心得 ...................................................................................…

写一个随机点名的程序

获取方式&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1fdCJ_3IYUl7v7x6I1zAWgg 提取码&#xff1a;1234 这里面用到JS当中的数组&#xff0c;random以及window.setInterval&#xff08;&#xff09;回调函数来进行实现的.