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

零拷贝的简单复习

PageCache

PageCache是内核缓冲区


DMA

没有DMA前的IO:整个数据的传输过程,都需要 CPU 亲自参与搬运数据的过程,而且这个过程中CPU 是不能做其他事情的

CPU发起IO
磁盘将数据放到磁盘缓冲区
CPU将磁盘缓冲区数据放到内核缓冲区
CPU将内核缓冲区放到用户缓冲区

DMA技术(直接内存访问):CPU 不再参与「将数据从磁盘控制器缓冲区搬运到内核空间」的工作,这部分工作全程由 DMA 完成

CPU发起IO
磁盘将数据放到磁盘缓冲区
DMA将磁盘缓冲区数据放到内核缓冲区
DMA将内核缓冲区放到用户缓冲区

有DMA的时候,CPU全盘负责磁盘IO

有了DMA后,DMA分担了IO中磁盘文件拷贝到磁盘缓冲区和磁盘缓冲区拷贝到内核缓冲区的工作


传统文件传输

四次拷贝:流程:磁盘文件->内核缓冲区->用户缓冲区->Socket缓存区->网卡

四次用户态和内核态的上下文切换:

read():用户态变成内核态,结束后内核态变回用户态

write():用户态变成内核态,结束后内核态变回用户态


优化文件传输的性能

  1. 减少系统调用次数,一次系统调用必然会发生 2 次上下文切换,因为上下文开销大,所以我们要尽量减少系统调用read(),write()
  2. 数据实际上不需要搬到用户空间,因为在用户空间我们并不会对数据「再加工」,因此用户的缓冲区是没有必要存在的

零拷贝

传统文件拷贝流程:

        DMA拷贝           CPU拷贝            CPU拷贝              DMA拷贝
磁盘文件————————>内核缓冲区————————>用户缓冲区————————>Socket缓存区————————>网卡

零拷贝实现方案:

  1. mmap+write 4次【上下文切换】+3次【数据拷贝】
  2. sendfile 2次【上下文切换】+3次【数据拷贝】

通过上面两种方法代替传统的read()+write()可以减少【上下文切换】和【数据拷贝】的次数

mmap+write调用次数:两次系统调用

mmap+write拷贝流程: 无需经过内核缓冲区

        DMA拷贝           CPU拷贝               DMA拷贝
磁盘文件————————>内核缓冲区————————>Socket缓存区————————>网卡

sendfile调用次数:只需一次系统调用它可以替代前面的 read () 和 write () 这两个系统调用,这样就可以减少一次系统调用,也就减少了 2 次上下文切换的开销

sendfile拷贝流程:无需经过内核缓冲区

        DMA拷贝           CPU拷贝               DMA拷贝
磁盘文件————————>内核缓冲区————————>Socket缓存区————————>网卡

真正的零拷贝

网卡支持 SG - DMA,sendfile就能实现真正的零拷贝

全程只需要DMA参与不需要CPU

一次系统调用

2次【上下文切换】+3次【数据拷贝】

拷贝流程:盘文件->内核缓冲区->网卡 无需CPU参与,无需经过Socket

         DMA拷贝           DMA拷贝
磁盘文件————————>内核缓冲区————————>网卡

PageCache(内核缓冲区)的作用

「内核缓冲区」实际上是磁盘高速缓存(PageCache)

DMA 把磁盘里的数据搬运到内存里,这样就可以用「读写磁盘」替换成「读写内存」

提高磁盘读写性能: PageCache 来缓存最近被访问的数据,当空间不足时淘汰最久未被访问的缓存

减少磁盘IO:

  1. 【预读功能】+【顺序读】
  2. 内核的 I/O 调度算法会缓存尽可能多的 I/O 请求在 PageCache 中最后「合并」成一个更大的 I/O 请求再发给磁盘

PageCache的缺点

大文件的传输,不应该使用 PageCache,也就是说不应该使用零拷贝技术

缓存被大量文件数据洗刷,几乎不可能利用到PageCache 中缓存的最近被访问的数据

所以大文件传输我们要用【直接IO+异步IO】

http://www.xdnf.cn/news/343477.html

相关文章:

  • Python变量作用域
  • C PRIMER PLUS——第6-2节:二维数组与多维数组
  • nginx 实现动静分离
  • 火影bug,未保证短时间数据一致性,拿这个例子讲一下Redis
  • Android Studio Gradle 中 只显示 Tasks 中没有 build 选项解决办法
  • 【Science Advances】北京邮电大学突破:基于MEMS-超表面的多阶涡旋光束高速切换技术
  • 缓冲区溢出分析
  • Java网络编程:深入剖析UDP数据报的奥秘与实践
  • WordPress插件depicter存在SQL注入漏洞(CVE-2025-2011)
  • Nginx 配置多个监听端口
  • 文件包含漏洞
  • 【JavaEE】TCP/IP协议(模型)
  • 使用ESPHome烧录固件到ESP32-C3并接入HomeAssistant
  • 森林生态学研究深度解析:R语言入门、生物多样性分析、机器学习建模与群落稳定性评估
  • WPF主窗体子窗体关联方法
  • WPF中解决数据绑定不匹配的问题
  • 中继器的作用
  • AI开发跃迁指南(第三章:第四维度2——weaviate cloud、weaviate docker安装配置及使用连接示例)
  • 【计算机网络】用户从输入网址到网页显示,期间发生了什么?
  • Nginx1.26.2安装包编译安装并配置stream模块
  • V型球阀材质性能深度解析:专攻颗粒、料浆与高腐蚀介质的工业利器-耀圣
  • WEB UI自动化测试之Pytest框架学习
  • RedHat磁盘的添加和扩容
  • 计数排序-详解
  • 从新手到高手:jQuery 全面进阶之路
  • 数字电子技术基础(五十六)——JK触发器
  • crawl4ai能替代scrapy等传统爬虫框架吗?
  • windows 部署 Kafka3.x KRaft 模式 不依赖 ZooKeeper
  • FPGA_Verilog实现QSPI驱动,完成FLASH程序固化
  • 学习黑客 MAC 地址深入了解