本文是对参考文章重要部分的摘录,同时进行简单地总结。linux
传统的 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 还得参与两次拷贝操做。网络
直接 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 结合使用。
物理磁盘 》 应用程序缓冲区 》 物理网卡缓冲区。app
有的时候,应用程序在数据进行传输的过程当中不须要对数据进行访问,那么,将数据从 Linux 的页缓存拷贝到用户进程的缓冲区中就能够彻底避免,传输的数据在页缓存中就能够获得处理。
在某些特殊的状况下,这种零拷贝技术能够得到较好的性能。Linux 中提供相似的系统调用主要有 mmap(),sendfile() 以及 splice()。
物理磁盘 》 内核页缓存 》 内核协议栈缓冲区 》 物理网卡缓冲区。异步
该零拷贝技术侧重于灵活地处理数据在用户进程的缓冲区和操做系统的页缓存之间的拷贝操做。这种方法延续了传统的通讯方式,这算是对前两种技术的一个折中,可是更加灵活。在 Linux 中,该方法主要利用了写时复制技术。ide
写时复制是计算机编程中的一种优化策略,它的基本思想是这样的:若是有多个应用程序须要同时访问同一块数据,那么能够为这些应用程序分配指向这块数据的指针,在每个应用程序看来,它们都拥有这块数据的一份数据拷贝,当其中一个应用程序须要对本身的这份数据拷贝进行修改的时候,就须要将数据真正地拷贝到该应用程序的地址空间中去,也就是说,该应用程序拥有了一份真正的私有数据拷贝,这样作是为了不该应用程序对这块数据作的更改被其余应用程序看到。这个过程对于应用程序来讲是透明的,若是应用程序永远不会对所访问的这块数据进行任何更改,那么就永远不须要将数据拷贝到应用程序本身的地址空间中去。
写时复制的最大好处就是能够节约内存。不过对于操做系统内核来讲,写时复制增长了其处理过程的复杂性。性能
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.
避免数据拷贝
将多种操做结合在一块儿
参考:Zero-copy、Linux 中的零拷贝技术,第 1 部分、Linux 中的零拷贝技术,第 2 部分、Linux 中直接 I/O 机制的介绍。