零拷贝技术 与 sendfile

举报
看,未来 发表于 2021/12/24 20:58:51 2021/12/24
【摘要】 愿打开此篇对你有所帮助。(图片来源网络)@[toc] 曾经的 I/O 过程 弊端分析可以看到,整个数据的传输过程,都要需要 CPU 亲自参与搬运数据的过程,而且这个过程,CPU 是不能做其他事情的。 解决方案DMA 技术,也就是直接内存访问(Direct Memory Access) 技术。在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参...

愿打开此篇对你有所帮助。

请添加图片描述

(图片来源网络)
@[toc]

曾经的 I/O 过程

在这里插入图片描述

弊端分析

可以看到,整个数据的传输过程,都要需要 CPU 亲自参与搬运数据的过程,而且这个过程,CPU 是不能做其他事情的。


解决方案

DMA 技术,也就是直接内存访问(Direct Memory Access) 技术。

在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情,这样 CPU 就可以去处理别的事务。

在这里插入图片描述


弊端

在这里插入图片描述

四次上下文切换 + 四次拷贝。

我就传一份数据,整这么麻烦。


解决方案

在 Linux 内核版本 2.1 中,提供了一个专门发送文件的系统调用函数 sendfile(),函数形式如下:

#include <sys/socket.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

在这里插入图片描述

如果网卡支持 SG-DMA(The Scatter-Gather Direct Memory Access)技术,我们可以进一步减少通过 CPU 把内核缓冲区里的数据拷贝到 socket 缓冲区的过程。

检查一下,这一步我来讲,不要去百度了,一个抄一个,都没有亲测,看着就烦。
在这里插入图片描述

注意看你的网卡叫什么名字,不一定就 eth0.

于是,从 Linux 内核 2.4 版本开始起,对于支持网卡支持 SG-DMA 技术的情况下, sendfile() 系统调用的过程发生了点变化。
在这里插入图片描述

这就是所谓的零拷贝(Zero-copy)技术,因为我们没有在内存层面去拷贝数据,也就是说全程没有通过 CPU 来搬运数据,所有的数据都是通过 DMA 来进行传输的。


现成应用场景

1、卡夫卡
2、nginx(我就是从nginx源码里看到sendfile,于是写了这一篇)


危险!!!

在传输大文件(GB 级别的文件)的时候,PageCache 会不起作用,那就白白浪费 DMA 多做的一次数据拷贝,造成性能的降低,即使使用了 PageCache 的零拷贝也会损失性能。

由于文件太大,可能某些部分的文件数据被再次访问的概率比较低,这样就会带来 2 个问题:

PageCache 由于长时间被大文件占据,其他「热点」的小文件可能就无法充分使用到 PageCache,于是这样磁盘读写的性能就会下降了;
PageCache 中的大文件数据,由于没有享受到缓存带来的好处,但却耗费 DMA 多拷贝到 PageCache 一次;

所以,针对大文件的传输,不应该使用 PageCache,也就是说不应该使用零拷贝技术,因为可能由于 PageCache 被大文件占据,而导致「热点」小文件无法利用到 PageCache,这样在高并发的环境下,会带来严重的性能问题。


解决方案

在高并发的场景下,针对大文件的传输的方式,应该使用「异步 I/O + 直接 I/O」来替代零拷贝技术。
在这里插入图片描述

如果不是高并发的大文件IO,我选择临时起个线程。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。