零拷贝
发布于
主要是介绍零拷贝的两种技术原理
what
零拷贝并不是不需要拷贝,而是减少不必要的拷贝次数。通常是说在IO读写过程中。
实际上,零拷贝是有广义和狭义之分,目前我们通常听到的零拷贝,包括上面这个定义减少不必要的拷贝次数
都是广义上的零拷贝。其实了解到这点就足够了。
我们知道,减少不必要的拷贝次数,就是为了提高效率。那零拷贝之前,是怎样的呢?
传统IO
传统IO
- 将磁盘文件,拷贝到操作系统内核缓冲区
- 将内核缓冲区的数据,拷贝到应用程序的buffer
- 将应用程序buffer中的数据,再拷贝到socket网络发送缓冲区(属于内核缓冲区)
- 将socket buffer数据,拷贝到网卡,由网卡进行网络传输
传统IO方式,读取磁盘文件进行网络发送,经过4次数据拷贝。但是第2、3次的拷贝明显没有什么帮助。
传统IO存在多次无效拷贝,还伴随着大量的上下文切换。
MMAP
这种方式使用mmap()代替了read()
- 磁盘的数据通过DMA拷贝到内核缓冲区
- 操作系统把这块内核缓冲区与应用程序共享,避免了用户缓冲区和内核缓冲区的跨界复制
- 应用程序调用write()直接从内核缓冲区的内容拷贝到socket缓冲区
- 最后系统将socket的数据传输到网卡,由网卡进行传输
MMAP减少了一次拷贝,提升了效率,但是并不减少上下文切换的次数。
SendFile
这种方式是使用sendfile代替了read+write操作
- 首先sendfile系统调用,通过DMA引擎将磁盘文件拷贝到内存缓冲区
- 在内核缓冲区,内核将数据拷贝到socket缓冲区
- 最后,DMA将数据从内核拷贝到网卡,由网卡传输
数据总共发生3次拷贝
对比
- 都是Linux内核提供,实现零拷贝的API
- sendfile是将读到内核缓冲区的数据,直接转到socket buffer,进行网络发送
- mmap是将磁盘文件读取到内核缓冲区后进行映射,和用户缓冲区共享数据,然后CPU在拷贝数据到socket buffer,进行网络发送