Linux中的zero-copy技术
本文是对参考文章重要部分的摘录,同时进行简单地总结。
零拷贝技术的相关背景知识
传统的 Linux 操作系统的标准 I/O 接口是基于数据拷贝操作的,即 I/O 操作会导致数据在操作系统内核地址空间的缓冲区和应用程序地址空间定义的缓冲区之间进行传输,这样做最大的好处是可以减少实际的物理磁盘 I/O 操作。但是数据传输过程中的数据拷贝操作却导致了极大的 CPU 开销,限制了操作系统有效进行数据传输操作的能力。
简单一点来说,零拷贝就是一种避免 CPU 将数据从一块存储拷贝到另外一块存储的技术。
零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率。而且,零拷贝技术减少了用户应用程序地址空间和操作系统内核地址空间之间因为上下文切换而带来的开销。
针对操作系统中的设备驱动程序、文件系统以及网络协议堆栈而出现的各种零拷贝技术极大地提升了特定应用程序的性能,并且使得这些应用程序可以更加有效地利用系统资源。
为什么需要零拷贝技术
很多网络服务器都是基于客户端 - 服务器这一模型的。在这种模型中,客户端向服务器端请求数据或者服务;服务器端则需要响应客户端发出的请求,并为客户端提供它所需要的数据。随着网络服务的逐渐普及,video 这类应用程序发展迅速。当今的计算机系统已经具备足够的能力去处理 video 这类应用程序对客户端所造成的重负荷,但是对于服务器端来说,它应付由 video 这类应用程序引起的网络通信量就显得捉襟见肘了。举个例子来说,当数据“写”操作或者数据“发送”操作的系统调用发出时,操作系统通常都会将数据从应用程序地址空间的缓冲区拷贝到操作系统内核的缓冲区中去。操作系统这样做的好处是接口简单,但是却在很大程度上损失了系统性能,因为这种数据拷贝操作不单需要占用 CPU 时间片,同时也需要占用额外的内存带宽。
一般来说,一个 CPU 时钟周期可以处理一位的数据。举例来说,一个 1 GHz 的处理器可以对 1Gbit/s 的网络链接进行传统的数据拷贝操作,但是如果是 10 Gbit/s 的网络,那么对于相同的处理器来说,零拷贝技术就变得非常重要了。
Linux 中传统服务器进行数据传输的流程如下。
当应用程序需要访问某块数据的时候,操作系统内核会先检查这块数据是不是因为前一次对相同文件的访问而已经被存放在操作系统内核地址空间的缓冲区内,如果在内核缓冲区中找不到这块数据,Linux 操作系统内核会先将这块数据从磁盘读出来放到操作系统内核的缓冲区里去。如果这个数据读取操作是由 DMA 完成的,那么在 DMA 进行数据读取的这一过程中,CPU 只是需要进行缓冲区管理,以及创建和处理 DMA ,除此之外,CPU 不需要再做更多的事情,DMA 执行完数据读取操作之后,会通知操作系统做进一步的处理。Linux 操作系统会根据 read() 系统调用指定的应用程序地址空间的地址,把这块数据存放到请求这块数据的应用程序的地址空间中去,在接下来的处理过程中,操作系统需要将数据再一次从用户应用程序地址空间的缓冲区拷贝到与网络堆栈相关的内核缓冲区中去,这个过程也是需要占用 CPU 的。数据拷贝操作结束以后,调用 write() 系统调用时,数据会被打包,然后发送到网络接口卡上去,这个操作也可以通过DMA完成。在数据传输的过程中,应用程序可以先返回进而执行其他的操作。之后,在调用 write() 系统调用的时候,用户应用程序缓冲区中的数据内容可以被安全的丢弃或者更改,因为操作系统已经在内核缓冲区中保留了一份数据拷贝,当数据被成功传送到硬件上之后,这份数据拷贝就可以被丢弃。
物理磁盘 》 内核页缓存 》 应用程序缓冲区 》 内核协议栈缓冲区 》 物理网卡缓冲区,去掉两次 DMA 拷贝操作,CPU 还得参与两次拷贝操作。
有哪几种零拷贝技术
Linux 中的直接 I/O
直接 I/O 是相对于缓存 I/O 的。缓存 I/O 又被称作标准 I/O,大多数文件系统的默认 I/O 操作都是缓存 I/O。在 Linux 的缓存 I/O 机制中,操作系统会将 I/O 的数据缓存在文件系统的页缓存( page cache )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。在缓存 I/O 机制中,DMA 方式可以将数据直接从磁盘读到页缓存中,或者将数据从页缓存直接写回到磁盘上,而不能直接在应用程序地址空间和磁盘之间进行数据传输,这样的话,数据在传输过程中需要在应用程序地址空间和页缓存之间进行多次数据拷贝操作,这些数据拷贝操作所带来的 CPU 以及内存开销是非常大的。
对于某些特殊的应用程序来说,避开操作系统内核缓冲区而直接在应用程序地址空间和磁盘之间传输数据会比使用操作系统内核缓冲区获取更好的性能,这就是直接 I/O 要解决的问题。直接 I/O 完全不需要 Linux 操作系统内核提供的页缓存的支持。但是直接 I/O 有时候也会对性能产生负面影响,所以应用程序使用直接 I/O 进行数据传输的时候通常会和使用异步 I/O 结合使用。
物理磁盘 》 应用程序缓冲区 》 物理网卡缓冲区。
针对数据传输不需要经过应用程序地址空间的零拷贝技术
有的时候,应用程序在数据进行传输的过程中不需要对数据进行访问,那么,将数据从 Linux 的页缓存拷贝到用户进程的缓冲区中就可以完全避免,传输的数据在页缓存中就可以得到处理。
在某些特殊的情况下,这种零拷贝技术可以获得较好的性能。Linux 中提供类似的系统调用主要有 mmap(),sendfile() 以及 splice()。
物理磁盘 》 内核页缓存 》 内核协议栈缓冲区 》 物理网卡缓冲区。
对应用程序地址空间和内核之间的数据传输进行优化的零拷贝技术
该零拷贝技术侧重于灵活地处理数据在用户进程的缓冲区和操作系统的页缓存之间的拷贝操作。这种方法延续了传统的通信方式,这算是对前两种技术的一个折中,但是更加灵活。在 Linux 中,该方法主要利用了写时复制技术。
写时复制是计算机编程中的一种优化策略,它的基本思想是这样的:如果有多个应用程序需要同时访问同一块数据,那么可以为这些应用程序分配指向这块数据的指针,在每一个应用程序看来,它们都拥有这块数据的一份数据拷贝,当其中一个应用程序需要对自己的这份数据拷贝进行修改的时候,就需要将数据真正地拷贝到该应用程序的地址空间中去,也就是说,该应用程序拥有了一份真正的私有数据拷贝,这样做是为了避免该应用程序对这块数据做的更改被其他应用程序看到。这个过程对于应用程序来说是透明的,如果应用程序永远不会对所访问的这块数据进行任何更改,那么就永远不需要将数据拷贝到应用程序自己的地址空间中去。
写时复制的最大好处就是可以节约内存。不过对于操作系统内核来说,写时复制增加了其处理过程的复杂性。
零拷贝技术概括
Zero-copy versions of operating system elements, such as device drivers, file systems, and network protocol stacks, greatly increase the performance of certain application programs and more efficiently utilize system resources.
Techniques for creating zero-copy software include the use of DMA-based copying and memory-mapping through an MMU. These features require specific hardware support and usually involve particular memory alignment requirements.
避免数据拷贝
- 避免操作系统内核缓冲区之间进行数据拷贝操作。
- 避免操作系统内核和用户应用程序地址空间这两者之间进行数据拷贝操作。
- 用户应用程序可以避开操作系统直接访问硬件存储。
- 数据传输尽量让 DMA 来做。
将多种操作结合在一起
- 避免不必要的系统调用和上下文切换。
- 需要拷贝的数据可以先被缓存起来。
- 对数据进行处理尽量让硬件来做。
参考:Zero-copy、Linux 中的零拷贝技术,第 1 部分、Linux 中的零拷贝技术,第 2 部分、Linux 中直接 I/O 机制的介绍。
Linux中的zero-copy技术的更多相关文章
- Linux 中的零拷贝技术,第 1 部分
概述 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.本文是本系列文章的第一部分,主要是介绍一些零拷贝技术的相关 ...
- 【转】浅析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 引言 传统的 ...
- Linux 中的零拷贝技术,第 2 部分
技术实现 本系列由两篇文章组成,介绍了当前用于 Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景.第一部分主要介绍了一些零拷贝技术的相关背景知识,简要概 ...
- 浅析 Linux 中的零拷贝技术
本文探讨Linux中 主要的几种零拷贝技术 以及零拷贝技术 适用的场景 .为了迅速建立起零拷贝的概念,我们拿一个常用的场景进行引入: 引文 在写一个服务端程序时(Web Server或者文件服务器), ...
- Linux中的零拷贝技术
转载:https://www.jianshu.com/p/fad3339e3448 引文## 在写一个服务端程序时(Web Server或者文件服务器),文件下载是一个基本功能.这时候服务端的任务是: ...
- Linux中的零拷贝
零拷贝 本文图片和一些内容均来自后面的参考,非原创只是把文章中的一些关键内容整理一下,算作是一个学习笔记. 传统的I/O操作 传统的IO操作是用户应用程序只是需要调用两个系统调用 read() 和 w ...
- 理解 Linux 网络栈(2):非虚拟化Linux 环境中的 Segmentation Offloading 技术
本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...
随机推荐
- [iOS]Objective-C 第一节课
Objective-C 第一节课 本节课的主要内容 创建Objective-C的第一个工程 HelloWorld Objective-C中的字符串 创建Objective-C的第一个工程 打开Xcod ...
- Tasks and Back stack 详解
原文地址:http://developer.android.com/guide/components/tasks-and-back-stack.html 一个应用往往包含很多activities.每个 ...
- Android Camera 调用流程总结
1.总体介绍 Android Camera框架从整体上看是一个client/service架构.有两个进程,一个是client进程,可以看成AP端,主要包括Java代码和一些native层的c/c+ ...
- 转发:Xcode插件
古人云“工欲善其事必先利其器”,打造一个强大的开发环境,是立即提升自身战斗力的绝佳途径!以下是搜集的一些有力的XCode插件. 1.全能搜索家CodePilot 2.0 你要找的是文件?是文件夹? ...
- 建立一个属于自己的AVR的RTOS
建立一个属于自己的AVR的RTOS(序) 建立一个属于自己的AVR的RTOS(第一篇:函数的运行) 建立一个属于自己的AVR的RTOS(第二篇:人工堆栈) 建立一个属于自己的AVR的RTOS(第三篇: ...
- phpstrom 2016.2 注册服务器地址
无意中发现的,亲测可用:http://114.215.133.70:41017
- Android开发之回调函数
写在前面,最近对回掉函数有了更深刻的认识,现在记录如下.由于在家看不到底层代码,在公司不能访问外网,现在只能凭靠记忆写这篇博文了,写错的地方还希望大神们指出来 其实给组件设置监听就是最典型的回掉函数的 ...
- 【python】matplotlib在windows下安装
昨晚装了好久的这玩意,终于在凌晨成功搞定,然后跑起了一个人人网抓取好友关系的脚本~开心. 以下是我参考的最给力的文档,全部安装一遍,就可以啦~ 但是!在安装前一定要先确认自己的python版本!本人自 ...
- Yaf 使用遇到的坑
yaf 使用心得: 1. yaf中使用__get魔术方法后,直接导致模板不能自动渲染,需要手动指定模板 ? 1 $this->getView()->display('index/in ...
- N皇后问题——递归求解
比较简单,废话不说,上代码: public class NQueen { //比如:position[1]=3,表示第一行的第三列有一个皇后 private int [] position; //总的 ...