零复制

零复-{}-制（；也译零拷-{}-贝）技术是指计算机执行操作时，CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。

 原理 
操作系统某些组件（例如驱动程序、文件系统和网络协议栈）若采用零复制技术，则能极大地增强了特定应用程序的性能，并更有效地利用系统资源。通过使CPU得以完成其他而非将机器中的数据复制到另一处的任务，性能也得到了增强。另外，零复制操作减少了在用户空间与内核空间之间切换模式的次数。

举例来说，如果要读取一个文件并通过网络发送它，传统方式下每个读/写调用周期都需要2次额外的复制数据（1次从内核复制到用户空间、1次从用户复制到内核空间）和4次上下文切换，而数据的复制都需要依靠CPU。而使用零复制技术通过使用内存映射文件mmap和一个写调用周期发送该文件，可将上下文切换减少到每个写调用2次，并避免之前2次额外的复制。sendfile调用完成同样的操作可将上下文切换减少到每个sendfile调用2次，并且同样不需要CPU复制数据（在用户空间和内核空间之间）。

零复制协议对于网络链路容量接近或超过CPU处理能力的高速网络尤为重要。在这种网络下，CPU几乎将所有时间都花在复制要传送的数据上，因此将成为使通信速率低于链路容量的瓶颈。

 硬件实现 
最早的实现为IBM ，其中一个程序可以指示从一个文件或设备复制数据块到另一处，无需先转移数据。

实现零复制的软件通常依靠基于直接記憶體存取（DMA）的复制，以及通过内存管理单元（MMU）的内存映射。这些功能需要特定硬件的支持，并通常涉及到特定存储器的对齐。

一种较新的方式为使用（HSA），便于CPU和GPU以及其他处理器传递指针。这需要CPU和GPU使用统一地址空间。

 程序访问 
数种操作系统都通过特定API支持文件的零复制。

Linux内核通过各个系统调用支持零复制，例如sys/socket.h的sendfile、sendfile64以及。它们部分在POSIX中指定，因此也存在于BSD内核或IBM AIX中，部分则是中独有。

Microsoft Windows通过TransmitFile API支持零复制。

Java输入流可以通过java.nio.channels支持零复制。FileChannel的transferTo()方法也可以支持零复制（如果底层操作系统支持）。

远程直接内存访问（RDMA）协议深度依赖零复制技术。

 参见 
 驱动程序
 嵌入式系统
 InfiniBand
 可编程输入输出
 Sockets Direct Protocol
 netsniff-ng

 参考资料 

Category:软件优化