当前位置: 首页 > news >正文

什么是零拷贝?以及数据在内存中的流动途径

零拷贝就是在以下的流动途径中,避免一些用户空间和内核缓冲区的拷贝。

“零拷贝”这个名字的“零”是指在数据传输过程中减少到最少甚至完全避免用户空间和内核空间之间的内存拷贝。传统的 I/O 操作中,数据通常要在内核空间和用户空间之间来回复制,造成了多次内存拷贝。零拷贝技术的目标是通过优化这些操作,尽可能减少数据拷贝的次数,理想情况下做到“零次拷贝”。

零拷贝的含义

  • “零”并不总是意味着绝对没有数据拷贝,而是指避免不必要的内存拷贝,尤其是避免内核空间和用户空间之间的多次拷贝。

传统方式 vs. 零拷贝

在传统的文件传输过程中(如通过网络发送文件),数据的拷贝过程大致如下:

  1. 从磁盘到内核缓冲区(第一次拷贝):数据从磁盘读入内核空间的缓冲区。
  2. 从内核缓冲区到用户空间缓冲区(第二次拷贝):数据从内核缓冲区复制到用户空间缓冲区。
  3. 从用户空间缓冲区回到内核缓冲区(第三次拷贝):数据从用户空间缓冲区复制回内核缓冲区,准备通过网络发送。
  4. 通过网络发送(可能有 DMA,但涉及系统总线传输):数据从内核缓冲区传输到网络接口卡(NIC),并通过网络发送。

零拷贝的目标是减少或消除步骤 2 和 3 中的数据拷贝。例如,通过 sendfile 系统调用,可以直接从内核缓冲区将数据发送到网络 socket,而无需将数据复制到用户空间再复制回来。这种方式避免了用户空间和内核空间之间的两次拷贝。

零拷贝的典型实现方式

  • sendfile 系统调用:直接将文件数据从内核缓冲区发送到网络 socket,减少了一次数据拷贝。

  • 内存映射 (mmap):将文件映射到用户空间,减少对文件的读操作拷贝数据次数。

  • DMA(Direct Memory Access):使用 DMA 技术让硬件设备直接从内存读取数据,绕过 CPU 的干预,从而减少拷贝和 CPU 资源的占用。

总结

“零拷贝”这个术语强调了减少甚至避免内存拷贝,特别是在内核空间和用户空间之间。这不仅可以减少 CPU 占用,还能提高系统的 I/O 性能,特别适用于高性能网络服务器、文件传输等场景。

在传统 I/O 操作中,数据在内存中的流动路径,尤其是在处理文件读取和网络发送时数据如何在内核空间和用户空间之间传递。让我们逐步解析这些操作:

1. 从磁盘读取数据到内核缓冲区

  • 内核缓冲区(Kernel Buffer):当你从磁盘读取数据时,操作系统首先将数据从磁盘读取到内核空间的一个缓冲区中。内核空间是操作系统核心代码运行的地方,具有最高权限。普通应用程序无法直接访问内核空间。

  • 过程:当应用程序执行诸如 read() 之类的系统调用时,操作系统会通过文件系统层将磁盘上的数据块加载到内核缓冲区中。这通常使用 DMA(直接内存访问)技术,由硬件控制器直接将数据从磁盘传输到内存,而无需占用 CPU 资源。

2. 将数据从内核缓冲区复制到用户空间缓冲区

  • 用户空间缓冲区(User Space Buffer):用户空间是应用程序运行的区域。为了确保系统的稳定性和安全性,应用程序运行在用户空间,不能直接访问内核空间中的数据。

  • 过程:内核完成数据读取后,会将数据从内核缓冲区复制到应用程序在用户空间分配的缓冲区中。这是通过 copy_to_user() 等机制完成的。这一步的原因是用户空间和内核空间隔离,应用程序无法直接访问内核缓冲区中的数据,所以需要通过拷贝将数据传递给用户空间。

3. 将数据从用户空间缓冲区复制回内核缓冲区

  • 为什么复制回内核缓冲区?:如果应用程序需要将数据发送到网络或写回磁盘,数据必须再次进入内核空间。这是因为网络栈和文件系统都运行在内核空间,而用户空间无法直接操作这些设备。

  • 过程:当应用程序需要发送数据(例如,通过 write()send() 调用),数据会从用户空间缓冲区再次复制回内核缓冲区。这个操作确保数据能够被内核控制的网络栈或文件系统处理。

4. 通过网络将数据从内核缓冲区发送出去

  • 网络发送的过程:一旦数据回到内核缓冲区,操作系统通过网络栈处理数据,并通过网络接口卡(NIC)将数据发送到网络上。这通常涉及到网络协议栈中的各层(如 TCP/IP 协议栈)的处理。

  • 网络接口卡(NIC):数据从内核缓冲区传输到 NIC,NIC 再将数据打包成网络帧,通过物理网络发送到目标地址。网络接口卡可能使用 DMA 直接从内存中读取数据,从而减轻 CPU 的负担。

总结这些步骤

  1. 读取数据:从磁盘到内核缓冲区(内核空间),通常使用 DMA 完成。
  2. 用户读取:将数据从内核缓冲区复制到用户空间缓冲区。
  3. 数据准备发送:将数据从用户空间缓冲区复制回内核缓冲区,准备通过网络发送。
  4. 网络发送:通过网络接口卡将数据发送到网络上。

这些步骤反映了传统 I/O 操作的常规数据流动路径,其中每次内核空间与用户空间之间的数据交互都会涉及一次数据拷贝,这也是为什么在高性能应用中,减少这些拷贝(通过零拷贝技术)会显著提升效率的原因。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 十三、OpenCVSharp的目标检测
  • 「入选文章」腾讯云AI代码助手 | AI助力,从零基础开发一个vscode插件
  • NGINX 之 location 匹配优先级
  • cdr工具介绍之刻刀工具
  • 重磅!RISC-V+OpenHarmony平板电脑发布
  • MySQL——高级查询(3)分组查询
  • 敲桌子游戏
  • Java OkHttp使用(二)
  • Java数组05:Arrays类
  • 多商户小程序审核存在商户入口无法通过
  • 消息中间件:Kafka消息丢失与堆积问题分析与解决方案
  • MySQL在Centos7环境安装
  • Oracle 同义词SYNONYM 的使用
  • 【GH】【EXCEL】P1: Write DATA SET from GH into EXCEL
  • 为什么要用云手机进行海外社交营销
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • django开发-定时任务的使用
  • ERLANG 网工修炼笔记 ---- UDP
  • isset在php5.6-和php7.0+的一些差异
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Java 内存分配及垃圾回收机制初探
  • java多线程
  • SpiderData 2019年2月13日 DApp数据排行榜
  • Theano - 导数
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • 二维平面内的碰撞检测【一】
  • 番外篇1:在Windows环境下安装JDK
  • 给第三方使用接口的 URL 签名实现
  • 解析 Webpack中import、require、按需加载的执行过程
  • 理解在java “”i=i++;”所发生的事情
  • 让你的分享飞起来——极光推出社会化分享组件
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 算法---两个栈实现一个队列
  • 跳前端坑前,先看看这个!!
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • #Linux(Source Insight安装及工程建立)
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #数学建模# 线性规划问题的Matlab求解
  • (10)STL算法之搜索(二) 二分查找
  • (poj1.3.2)1791(构造法模拟)
  • (第三期)书生大模型实战营——InternVL(冷笑话大师)部署微调实践
  • (四)汇编语言——简单程序
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)ObjectiveC 深浅拷贝学习
  • .bat批处理(六):替换字符串中匹配的子串
  • .gitignore文件设置了忽略但不生效
  • .net core 控制台应用程序读取配置文件app.config
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .net 获取某一天 在当月是 第几周 函数
  • .NET8 动态添加定时任务(CRON Expression, Whatever)
  • .net中我喜欢的两种验证码
  • @取消转义