Netty入门学习笔记(三)-- 零拷贝

学前准备

上篇文章中我们了解了三种 IO 模型以及操作系统的用户态和内核态,接下来需要继续学习 IO 模型中关于零拷贝的知识。

本文学习自 linuxjournal:https://www.linuxjournal.com/article/6345

零拷贝入坑

什么是零拷贝

零拷贝从字面意思理解好像就是无需拷贝的意思。真正的意思是指从硬件到通过网络发送出去这个过程中,数据多次拷贝没有 CPU 参与。

补充:
DMA(Direct Memory Access),中文名称:直接内存存取。DMA 的出现,是一次解放 CPU 的革命,即通过 DMA 通道直接将数据从磁盘拷贝到内核缓冲区中,而无需 CPU 参加拷贝。

传统 IO

Netty入门学习笔记(三)-- 零拷贝_第1张图片
如上图,从数据从 hard driveprotocol engine 过程中,经过 4 次数据拷贝,4 次的状态切换。

执行过程

  1. 初始调用时处于用户态,无权限调用外设,需要从用户态转换为内核态,并通过 DMA 通道将数据从磁盘拷贝到内核缓存区中。(此处涉及一次拷贝一次状态切换
  2. 紧接着,CPU 参与数据拷贝,将数据从内核缓存区拷贝到用户缓存区中,拷贝完毕后状态从内核态切换到用户态(此处也涉及一次拷贝一次状态切换
  3. 准备将数据通过网络传输,需要将数据拷贝到 socket 缓存区中。CPU 参与将数据从用户缓存区拷贝到 socket 缓存区,并进行一次状态切换。(此处也涉及一次拷贝一次状态切换
  4. 紧接着通过 DMA 通道将数据拷贝到网络协议引擎中。(此处涉及一次拷贝
  5. 上述完成后,请求会从内核态切换为用户态。(涉及一次状态切换

上述便是传统 IO 的基本执行流程。其中 CPU 参与拷贝,不仅消耗宝贵的 CPU 时钟,还导致数据存在多个备份,造成资源的浪费。后续 IO 优化也是基于减少 CPU 参与次数以及数据拷贝次数来进行的。

mmap IO

Netty入门学习笔记(三)-- 零拷贝_第2张图片
如上图,从数据从 hard driveprotocol engine 过程中,经过 3 次数据拷贝,4 次的状态切换。

执行过程

  1. 初始调用时处于用户态,无权限调用外设,需要从用户态转换为内核态,并通过 DMA 通道将数据从磁盘拷贝到内核缓存区中。(此处涉及一次拷贝一次状态切换
  2. mmap 在这里做了一层地址映射,将内核缓存区中数据地址共享到用户缓存区中,如此便可以减少一次数据的拷贝,并将数据通过 CPU 拷贝到 socket 缓冲池中,紧接着内核态切换为用户态。(此处涉及一次拷贝一次状态切换
  3. 由用户态切换回内核态,将数据从内核缓存区(此处涉及一次状态切换
  4. 此后 socket 缓冲区通过 DMA 通道将数据拷贝到网络协议引擎中,并从内核态切换回用户态。(此处涉及一次拷贝一次状态切换

对比与传统 IO,mmap 设计上不绕过用户空间,而是建立地址映射来减少拷贝次数。尽管如此,依旧有不必要的状态切换以及 CPU 参与数据拷贝,数据备份导致资源浪费,此方法在后续会进一步优化。

Linux2.1中 sendFile 函数

Netty入门学习笔记(三)-- 零拷贝_第3张图片
如上图,从数据从 hard driveprotocol engine 过程中,经过 3 次数据拷贝,2 次的状态切换。

执行过程

  1. 初始调用时处于用户态,无权限调用外设,需要从用户态转换为内核态,并通过 DMA 通道将数据从磁盘拷贝到内核缓存区中。(此处涉及一次拷贝一次状态切换
  2. 内核缓存区将文件的通过 CPU 拷贝到 socket 缓存区中,紧接着从内核态切换回用户态,(此处涉及一次拷贝一次状态切换
  3. 再通过 DMA 通道将数据拷贝到网络协议引擎中。(此处涉及一次拷贝

优化后 sendFile 函数

Netty入门学习笔记(三)-- 零拷贝_第4张图片
如上图,从数据从 hard driveprotocol engine 过程中,经过 2 次数据拷贝,2 次的状态切换。

执行过程

  1. 初始调用时处于用户态,无权限调用外设,需要从用户态转换为内核态,并通过 DMA 通道将数据从磁盘拷贝到内核缓存区中。(此处涉及一次拷贝一次状态切换
  2. 内核缓存区将文件的元数据拷贝到 socket 缓存区中(这里属于 CPU 拷贝,但是拷贝数据太小,忽略不计。原因:文件元数据信息包括:文件大小,格式等,数据极小 ),紧接着通过 DMA 通道将数据拷贝到网络协议引擎中,并从内核态切换回用户态。(此处涉及一次拷贝一次状态切换

优化后的 sendFile 算是达到了我们所说的零拷贝,在绕过用户空间,尽可能的消除不必要的数据副本,减少了上下文切换带来的资源开销。从目前来看,已经达到最优的性能方案。也许未来在硬件升级后,会有更强大的支持,我们拭目以待。

你可能感兴趣的:(Netty,入坑指南)