零拷贝

问题 :

  • 零拷贝解决的是什么问题
  • 零拷贝的本质是什么
    文章部分知识来自参考链接中朱大的文章,半原创

概述

  假如有以下场景:你需要发送一张图片给某个朋友,那么选择好图片后(read),建立连接发送。(write)

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

  这个过程可以见下图
1297993-20190929142438468-1914826245.png
  可以看到共4个步骤 :

  1. 调用read的时候,文件A从磁盘拷贝kernel模式下 (read)
  2. CPU控制将 kernel 模式数据拷贝到user模式下 (read)
  3. 调用 write时,先将user模式下的内容拷贝到kernel模式下 (write)
  4. 最后将kernel 模式下的socket buffer 拷贝到网卡设备中传输 (write)
      可以看到1到4中,要是网卡设备直接磁盘中拿到数据直接发送就不用2,3步骤中的拷贝了,即是磁盘数据 -> kernel模式下内存数据 -> 网卡设备发送

Zero Copy

  零拷贝是如何工作的呢?

  1. transferTo()方法使得文件A的内容直接拷贝到一个read buffer(kernel buffer)中;
  2. 然后数据(kernel buffer)拷贝到socket buffer中。
  3. 最后将socket buffer中的数据拷贝到网卡设备(protocol engine)中传输;
    这显然是一个伟大的进步:这里把上下文的切换次数从4次减少到2次,同时也把数据copy的次数从4次降低到了3次。
    1297993-20190929145808455-596176468.png

进阶

  我们看到 socket buffer 那里的复制要是可以提高就好了,Linux2.4 以后进行了优化,

  1. 将文件拷贝到kernel buffer中;
  2. 向socket buffer中追加当前要发生的数据在kernel buffer中的位置和偏移量;
  3. 根据socket buffer中的位置和偏移量直接将kernel buffer的数据copy到网卡设备(protocol engine)中;
      采用追加的方式,那样就不用每次都进行拷贝。
    1297993-20190929150127927-107816186.png

概述

  整个过程就像这样子。
1297993-20190929145517667-770207685.png

参考资料

原文地址:https://www.cnblogs.com/Benjious/p/11608012.html