问题 :
- 零拷贝解决的是什么问题
- 零拷贝的本质是什么
文章部分知识来自参考链接中朱大的文章,半原创
概述
假如有以下场景:你需要发送一张图片给某个朋友,那么选择好图片后(read),建立连接发送。(write)
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
这个过程可以见下图
可以看到共4个步骤 :
- 调用read的时候,文件A从磁盘拷贝kernel模式下 (read)
- CPU控制将 kernel 模式数据拷贝到user模式下 (read)
- 调用 write时,先将user模式下的内容拷贝到kernel模式下 (write)
- 最后将kernel 模式下的socket buffer 拷贝到网卡设备中传输 (write)
可以看到1到4中,要是网卡设备直接磁盘中拿到数据直接发送就不用2,3步骤中的拷贝了,即是磁盘数据 -> kernel模式下内存数据 -> 网卡设备发送
Zero Copy
零拷贝是如何工作的呢?
- transferTo()方法使得文件A的内容直接拷贝到一个read buffer(kernel buffer)中;
- 然后数据(kernel buffer)拷贝到socket buffer中。
- 最后将socket buffer中的数据拷贝到网卡设备(protocol engine)中传输;
这显然是一个伟大的进步:这里把上下文的切换次数从4次减少到2次,同时也把数据copy的次数从4次降低到了3次。
进阶
我们看到 socket buffer 那里的复制要是可以提高就好了,Linux2.4 以后进行了优化,
- 将文件拷贝到kernel buffer中;
- 向socket buffer中追加当前要发生的数据在kernel buffer中的位置和偏移量;
- 根据socket buffer中的位置和偏移量直接将kernel buffer的数据copy到网卡设备(protocol engine)中;
采用追加的方式,那样就不用每次都进行拷贝。
概述
整个过程就像这样子。