Linux 零拷贝技术
简介
零拷贝(zero-copy)技术可以减少数据拷贝和共享总线操作的次数,消除通信数据在存储器之间不必要的中间拷贝过程,有效地提高通信效率,是设计高速接口通道、实现高速服务器和路由器的关键技术之一。数据拷贝受制于传统的操作系统或通信协议,限制了通信性能。采用零拷贝技术,通过减少数据拷贝次数,简化协议处理的层次,在应用和网络间提供更快的数据通路,可以有效地降低通信延迟,增加网络吞吐率。
抛砖引玉
为了更好地理解问题的解决方案,我们首先需要了解问题本身。 让我们看看一个网络服务器通过网络将存储在文件中的数据提供给客户端这个简单过程中涉及的内容。 以下是一些示例代码:
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
看起来只有两次系统操作,但数据已经被复制了4次,并且执行了多次用户/内核空间的上下文切换。如下图,我们了解一下这些系统调用所涉及的处理过程,顶部显示上下文切换,底部显示拷贝操作。

两个系统调用中的拷贝过程
第一步:read系统调用导致上下文从用户模式切换到内核模式。第一个副本由DMA引擎执行,DMA引擎从磁盘读取文件内容并将它们存储到内核地址空间缓冲区中。
第二步:将数据从内核缓冲区复制到用户缓冲区,并且read系统调用返回。read调用返回导致上下文从内核切换回用户模式。现在数据存储在用户地址空间缓冲区中。
第三步:write系统调用导致上下文从用户模式切换到内核模式。执行第三次复制,以再次将数据放入内核地址空间缓冲区。这个时候,数据被放入一个不同的缓冲区,一个与sockets相关联的缓冲区。
第四步:write系统调用返回,执行第四个上下文切换,将数据从内核缓冲区传递到协议引擎。
正如现在所看到的,很多数据复制操作并不是真正需要的。可以消除一些复制操作以减少开销并提高性能。需要引入具有非常先进的硬件,绕过主存储器,将数据直接传输到另一个设备,这引入了一些复杂性,同时并不是所有硬件都支持。
mmap
mmap:一个文件或者其它对象映射进内存。
消除复制的一种方法是调用mmap来替代read。 例如:
tmp_buf = mmap(file, len);
write(socket, tmp_buf, len);

说明
第一步:mmap系统调用导致DMA引擎将文件内容复制到内核缓冲区中。然后与用户进程共享缓冲区,而不在内核和用户存储器空间之间执行任何复制。
第二步:write系统调用导致内核将数据从原始内核缓冲区复制到与套接字相关联的内核缓冲区中。
第三步:当DMA引擎将数据从内核套接字缓冲区传递到协议引擎时,发生第三次复制。
通过使用mmap而不是read,已经削减了一半的内核复制的数据量。当传输大量数据时,这产生相当好的结果。然而,这种改进是有代价的,使用mmap + write方法时存在隐藏的缺陷。当内存映射一个文件,然后调用write,而另一个进程截断同一个文件,你会陷入其中之一。你的写系统调用将由总线错误信号SIGBUS中断,因为你执行了错误的存储器访问。该信号的默认行为是杀死进程和转储核心,这不是网络服务器最理想的操作。有两种方法来解决这个问题。
第一种方法是为SIGBUS信号安装一个信号处理程序,然后在处理程序中调用return。
第二个解决方案涉及内核中的文件租赁(在Microsoft Windows中称为“机会锁定”)。
sendfile
在内核版本2.1中,引入了sendfile系统调用,以简化网络上和两个本地文件之间的数据传输。 sendfile的引入不仅减少了数据复制,还减少了上下文切换。 使用如下:
sendfile(socket, file, len);

说明
第一步:sendfile系统调用使文件内容被DMA引擎复制到内核缓冲区中。 然后内核将数据复制到与套接字相关联的内核缓冲区中。
第二步:当DMA引擎将数据从内核套接字缓冲区传递到协议引擎时,发生第三次复制。
支持聚集操作的硬件
到目前为止,我们已经能够避免一些内核复制操作,但是我们仍然有一次内核复制操作。 这也可以避免吗? 当然,这需要硬件的一点帮助。 为了消除内核所做的所有数据复制,我们需要一个支持聚集操作的网络接口。 这仅仅意味着等待传输的数据不需要在连续的内存空间中, 这些数据可以分散在存储器的各个位置。 在内核版本2.4中,修改了套接字缓冲区描述符以适应这些要求——在Linux下称为零拷贝。 这种方法不仅减少了多个上下文切换,还完全消除了处理器的数据复制操作。

支持聚集操作的硬件从内存的多个位置获取数据,消除内存拷贝
第一步:sendfile系统调用使文件内容被DMA引擎复制到内核缓冲区中。
第二步:没有数据被直接复制到套接字缓冲区。相反,只有描述符(关于数据的位置和长度的信息)附加到Socket缓冲区。DMA引擎将数据直接从内核缓冲区传递到协议引擎,从而消除最后剩下的一次内存拷贝。
在Java中的应用
可使用Java NIO中的FileChannel.transferTo()方法实现零拷贝。
transferTo() 方法将数据从文件通道传输到了给定的可写字节通道。在内部,它依赖底层操作系统对零拷贝的支持;在 UNIX 和各种 Linux 系统中,此调用被传递到 sendfile() 系统调用中。
参考
- http://www.linuxjournal.com/article/6345
- https://leokongwq.github.io/2017/01/12/linux-zero-copy.html
- https://www.ibm.com/developerworks/cn/java/j-zerocopy/
Linux 零拷贝技术的更多相关文章
- Linux零拷贝技术 直接 io
Linux零拷贝技术 .https://kknews.cc/code/2yeazxe.html https://zhuanlan.zhihu.com/p/76640160 https://clou ...
- Linux零拷贝技术
本文转载自Linux零拷贝技术 导语 本文讲解 Linux 的零拷贝技术,云计算是一门很庞大的技术学科,融合了很多技术,Linux 算是比较基础的技术,所以,学好 Linux 对于云计算的学习会有比较 ...
- Linux零拷贝技术,看完这篇文章就懂了
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复 「1024」 即可领取,欢迎大家关注,二维码文末可以扫. 本文讲解 ...
- Linux 中的零拷贝技术,第 2 部分
技术实现 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.第一部分主要介绍了一些零拷贝技术的相关背景知识,简要概 ...
- Linux 中的零拷贝技术,第 1 部分
概述 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.本文是本系列文章的第一部分,主要是介绍一些零拷贝技术的相关 ...
- Linux中的零拷贝技术
转载:https://www.jianshu.com/p/fad3339e3448 引文## 在写一个服务端程序时(Web Server或者文件服务器),文件下载是一个基本功能.这时候服务端的任务是: ...
- 【转】浅析Linux中的零拷贝技术
本文探讨Linux中主要的几种零拷贝技术以及零拷贝技术适用的场景.为了迅速建立起零拷贝的概念,我们拿一个常用的场景进行引入: 引文## 在写一个服务端程序时(Web Server或者文件服务器),文件 ...
- [转帖]Linux 中的零拷贝技术,第 2 部分
Linux 中的零拷贝技术,第 2 部分 https://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy2/index.html Linux 中 ...
- [转帖]Linux 中的零拷贝技术,第 1 部分
Linux 中的零拷贝技术,第 1 部分 https://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy1/index.html 引言 传统的 ...
随机推荐
- [译]Selenium Python文档:七、WebDriver API接口
由于API文档格式不太适合cnblog博客,暂且翻译一部分,且暂未校对 注意:这不是官方文档,官方 API文档在这里. 本章包含Selenium WebDriver的所有接口 推荐import风格 本 ...
- Butter Knife使用详解
Butter Knife Github地址: https://github.com/JakeWharton/butterknife 官方说明给出的解释是 Bind Android views and ...
- 用Java实现将多级文件夹下的所有文件统一放到一个文件夹中
每次下了电影(男生懂得呦),每部电影都放在一个单独的文件夹里,看的时候很是不方便啊,一直重复着进入文件夹.后退,再进.再退的操作,而手动把这些电影全部复制出来又太繁琐.因此为了解决这个问题,用IO写了 ...
- Yahoo前端优化十四条军规
相信互联网已经越来越成为人们生活中不可或缺的一部分.Ajax,flex等等富客户端的应用使得人们越加“幸福”地体验着许多原先只能在C/S实 现的功能. 比如Google机会已经把最基本的office应 ...
- 【前端童鞋看过来!】给大家分享网盘里前端相关书籍,主要是和网络通信(HTTP/TCP/IP)及javascript相关的
百度云链接:https://pan.baidu.com/s/1kUPdf5H(无密码) 截图: <HTTP权威指南> [豆瓣书评]:此书第一部分是HTTP的概略,如果你没有时间,通读第一部 ...
- 原生JS实现弹出窗口的拖拽
上一篇说了一下弹出窗口功能的实现思路,一般情况下紧接着就会需要做到弹窗的移动,当然现在有很插件.库比如hammer可以使用,效率也非常好.但我觉得还是有必要了解一下原生JS的实现思路及方式,如下: 思 ...
- CentOS下查看nginx和php的编译参数
在已经编译安装好的nginx和php的server上是可以查看之前编译时候的参数的,方法如下. 1.查看nginx的编译参数 # nginx -V nginx version: nginx/1.9.4 ...
- HANA CDS与ABAP CDS
如果你在网络或者SCN上面搜索CDS,即SAP的Core Data Services,你会很容易地找到类似“Core Data Services(CDS)是一个在SAP HANA中用于定义和消费富语义 ...
- IOS开发创建开发证书及发布App应用(五)——编译应用
5.编译应用 最近升级ios7,一直没有时间写,终于搞完了,完成之前没有完成的工作 由于适配ios7,所以Xcode也升级到5了,所以下面截图基本在Xcode5上,以前的版本基本也差不多的 打开项目的 ...
- C++ 虚函数相关,从头到尾捋一遍
众所周知,C++虚函数是一大难点,也是面试过程中必考部分.此次,从虚函数的相关概念.虚函数表.纯虚函数.再到虚继承等等跟虚函数相关部分,做一个比较细致的整理和复习. 虚函数 OOP的核心思想是多态性( ...