NVME协议总结

2023-12-21 12:19:11

NVMe over PCIe协议,定义了NVMe协议的使用范围、指令集、寄存器配置规范等。

1?NVMe SSD
1.1基本架构
整体来看,NVMe SSD可以分为三部分,host端的驱动(NVMe官网以及linux、Windows已经集成了相应的驱动)、PCIe+NVMe实现的控制器以及FTL+NAND Flash的存储介质。

为了便于理解主机和NVMe设备的关系,我们这里简化NVMe设备的内部结构。如图所示为NVMe白皮书中的配图,这里主机称为Host,而NVMe设备称为Controller(控制器)。主机和控制器之间通过共享内存的队列实现交互。

NVMe的队列分为2种,其中一种是用于管理的队列,称为Admin Queue(管理队列),仅有一个,另外一种是命令队列(Command Queue),最多可以有65535个。其中命令队列的数量和模式都是通过管理队列来设置的。其中每一个队列实际上是一个队列对,也就是包括两个队列,分别是提交队列(Submission Queue)和完成队列(Completion Queue)。提交队列用于主机端向NVMe设备发送NVMe命令,而完成队列则用于NVMe设备向主机反馈命令执行情况。实际上NVMe还有另外一种模式,就是多个提交队列共享同一个完成队列的情况。其实这里提交队列和完成队列就是内存的一个区域。在数据结构原理上这里的队列其实是一个环形缓冲区。

1.2 NVMe控制器
NVMe控制器实质上为DMA + multi Queue,DMA负责数据搬运(指令+用户数据),多队列负责发挥闪存的并行能力。

NVMe协议的原理也是如此,它本质是上建立了多个计算机与存储设备的通路,这样搬运数据的速度自然就提高了。在NVMe协议中,多个通路其实就是多个队列,具体如图7所示。在SATA中计算机与存储设备只能有一个队列,即使是多CPU情况下,所有请求只能经过这样一个狭窄的道路。而NVMe协议可以最多有64K个队列,每个CPU或者核心都可以有一个队列,这样并发程度大大提升,性能也自然更高了。

目前基于SCSI协议的SAS和SATA只能是单个队列而且每个队列的深度也比较低,分别是254和32的队列深度。而NVMe协议设计之初就考虑了该问题,它的最大队列数量可以是64K(65535个命令队列和1个管理队列),而每个队列的深度可以高达64K。

NVMe通过一种门铃机制(Doorbell)来告知控制器命令队列是否有新数请求/命令。也就是说每个队列都有一个门铃指针。对于发送队列来说,这个指针表示的是发送队列的尾指针。主机端将数据写入到发送队列后,更新映射到位于设备寄存器空间中的门铃的尾指针。此时,在控制器端就知道有新的请求/命令到来,接下来就可以进行对其进行处理。

当控制器完成一个NVMe请求时,通过完成队列来把完成的结果告知主机端。与发送队列不同,完成队列是通过中断机制(可以是INTx,MSI或MSIx)告诉主机端。如图4是一个命令的完整处理流程。

2 核心概念
2.1 Namespace
Namespace是一定数量逻辑块(LB)的集合,属性在Identify Controller中的数据结构中定义。

2.2 Fused Operations
Fused Operations可以理解为聚合操作,只能聚合两条命令,并且这两条命令在队列中应保持相邻顺序。协议中只有NVM指令才有聚合操作。还需要保证聚合操作的两条命令读写的原子性,参考Compare and Write例子。

2.3 指令执行顺序
除了聚合操作(Fused Operations),每一条SQ中的命令都是独立的,不必考虑RAW等数据相关问题,即使考虑,也是host应该解决的问题。

2.4 写单元的原子性
控制器需要支持写单元的原子性。但有时也能通过host配置Write Atomicity feature,减小原子性单元的大小,提高性能。

2.5 元数据
数据的额外信息,相当于提供校验功能。可选的方式。

2.6 仲裁机制
用来选择下一次执行的命令的SQ的机制,三种仲裁方式:
1.RR(每个队列优先级相同,轮转调度)
2.带权重的RR(队列有4种优先级,根据优先级调度)
3.自定义实现

2.7 逻辑块(LB)
NVMe定义的最小的读写单元,2KB、4KB……,用LBA来标识块地址,LBA range则表示物理上连续的逻辑块集合。

2.8 Queue Pair
由SQ(提交队列)与CQ(完成队列)组成,host通过SQ提交命令,NVMe Controller通过CQ提交完成命令。

2.9 NVM 子系统
NVM子系统包括控制器、NVM存储介质以及控制器与NVM之间的接口。

3 NVME命令

下图是NMVe命令的具体格式,如果大家了解TCP/IP协议或者SCSI协议,那么理解本图将相当容易。在图4中每一行为8个字节,命令大小总共为64字节。

其中Command Identifier标识一个具体的命令。Namespace Identifier则表示命令发送到那个命名空间。Data Pointer 1 和Data Pointer 2则用于标识数据的具体位置。

这里有两点需要说明:

  • NVMe的一个控制器下面可以有多个命名空间(Namespace),通过Namespace ID来标识的。
  • 命令与数据是分离的,并不像TCP那样数据在命令后面。

我们这里重点介绍一下Command Identifier,该字段占用4个字节的空间。虽然仅有4个字节,但有分为3大部分,6小部分,具体如图6所示。

我们以从低位到高位的顺序分别介绍一下各个字段的含义:

  • OPC: 全称为Opcode,也就是被执行命令的操作码。具体来说就是想让控制器干什么,比如读数据、写数据或者刷写等。

  • FUSE: 全称为Fused Operation, 用于标识该命令是普通命令还是复合命令。如图8是白皮书对该字段的说明。

  • PSDT: 全称为PRP or SGL for Data Transfer,这个用于说明存储数据的内存的组织形式。

4 NVME性能

通过上图可以清楚的看到SAS和SATA设备与NVMe设备的性能差异,特别是对于读操作,NVMe有绝对的性能优势。

文章来源:https://blog.csdn.net/weixin_43778179/article/details/135123273
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。