零拷贝
零拷贝还是很重要的,比如可能有人考你KAFKA的高性能是怎么实现的啊
这其中就有零拷贝
对于JAVA程序员来说,说到零拷贝只需要说出来
1 底层是sendFile
2 JAVA中的api是 FileChannel.transferTo()
如果想多说点
零拷贝技术通过 DMA (Direct Memory Access )技术将文件内容复制到内核模式下的 Read
Buffer 中 。不过没有数据被复制到 Socket Buffer,相反只有包含数据的位置和长度的信息的文
件描述符被加到 Socket Buffer 中 。 DMA 引擎直接将数据从内核模式中传递到网卡设备(协议
引擎)。这里数据只经历了 2 次复制就从磁盘中传送出去了 , 并且上下文切换也变成了 2 次。
零拷贝是针对内核模式而言的,数据在内核模式下实现了零拷贝 。
什么是 DMA 技术?简单理解就是,在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情,
这样 CPU 就可以去处理别的事务。
从 Linux 内核 2.4
版本开始起,对于支持网卡支持 SG-DMA 技术的情况下, sendfile()
系统调用的过程发生了点变化,具体过程如下:
- 第一步,通过 DMA 将磁盘上的数据拷贝到内核缓冲区里;
- 第二步,缓冲区描述符和数据长度传到 socket 缓冲区,这样网卡的 SG-DMA 控制器就可以直接将内核缓存中的数据拷贝到网卡的缓冲区里,此过程不需要将数据从操作系统内核缓冲区拷贝到 socket 缓冲区中,这样就减少了一次数据拷贝;
零拷贝技术的文件传输方式相比传统文件传输的方式,减少了 2 次上下文切换和数据拷贝次数,只需要 2 次上下文切换和数据拷贝次数,就可以完成文件的传输,而且 2 次的数据拷贝过程,都不需要通过 CPU,2 次都是由 DMA 来搬运。
用户态到内核态切换必须是2次,这个没法省。因为从内核态必须得回去。