零拷贝主要是为了解决用户态与内核态之间数据的拷贝,减少cpu的负担。下面的图描述了常见的数据处理过程。
![](https://img.haomeiwen.com/i11383162/903b9d701acd4a8a.png)
图中一共出现了四次拷贝,即使使用了DMA
来处理与硬件的通讯,cpu仍然需要处理两次拷贝。
零拷贝的实现方法
1. 使用mmap
我们减少拷贝次数的一种方法是调用mmap()来代替read调用。操作系统会通过内核缓冲区与应用程序共享,应用程序再调用write()操作,操作系统直接将内核缓冲区的内容拷贝到socket缓冲区。这个拷贝过程一直在内核态。
![](https://img.haomeiwen.com/i11383162/62aee9afeec2a082.png)
当拷贝数据量很大时,这种方式很明显提升了效率,但是也是存在缺陷的,作为共享缓冲区,他很有可能被其他的进程修改,所以通常会对mmap()的文件加锁。
2. 使用sendfile
系统调用sendfile()在代表输入文件的描述符in_fd和代表输出文件的描述符out_fd之间传送文件内容。描述符out_fd必须指向的是一个套接字,而in_fd指向的文件必须是mmap的。这些局限了sendfile的使用。这里将in_fd指向文件标记为mmap,是为了用户态对文件的修改。当然这里唯一的一次cpu拷贝也可以由dma引擎执行,只不过还需将带有文件位置和长度信息的缓冲区描述符添加到socket缓冲区中,dma引擎会直接将页缓存的数据拷贝到协议引擎中,实现真正的零拷贝。
网友评论