NVMe 将 I/O 提交到本地 PCIe 设备

本文涉及到的功能函数在下面链接都能找到
spdk函数功能

这是我对nvme操作存储设备的理解
用户态的spdk驱动,通过pcie传输nvme协议(cmd 、数据)与新型的SSD存储设备交互,即读写SSD设备
在这里插入图片描述
spdk:SPDK(Storage Performance Development Kit)是一个开源项目,旨在提供高性能、低延迟的存储系统开发工具集。SPDK 主要面向数据中心、云计算和嵌入式系统。使用 NVMe SSD 作为后端存储的应用软件加速库。该软件库的核心是实现了用户态、异步、无锁、轮询方式的 NVMe 驱动

nvme:NVMe(Non-Volatile Memory Express)是一种用于连接固态硬盘(SSD)和其他非易失性存储设备的通信协议和接口标准。它旨在充分发挥固态硬盘的性能潜力,提供了一种高效、低延迟的通信方式,以加速数据存储和检索操作。以下是关于NVMe的一些重要信息

高性能:NVMe是为固态硬盘设计的,充分利用了固态存储的低访问延迟和高数据吞吐量。相对于传统的SATA接口,NVMe SSDs通常能够提供更快的数据传输速度和更低的I/O延迟。

并行性:NVMe支持大量并行命令队列,允许同时进行多个读写操作。这提高了固态硬盘的多任务性能,特别适用于数据中心和高性能计算环境。

低CPU开销:NVMe协议设计旨在降低CPU的负载,使其更加高效。这意味着更多的计算资源可以用于应用程序,而不是用于管理存储设备。

多命名空间:NVMe支持多个命名空间,使得一个物理NVMe设备可以被划分为多个逻辑存储单元。这对于虚拟化和多租户环境非常有用。

热插拔:NVMe设备通常支持热插拔,这意味着可以在系统运行时添加或移除NVMe SSDs,而不需要关闭服务器。

广泛应用:NVMe在数据中心、企业存储、工作站和个人电脑等多个领域得到广泛应用。它适用于需要高性能存储解决方案的各种场景。

NVMe over Fabrics(NVMe-oF):除了本地NVMe设备,NVMe还支持通过网络传输NVMe命令和数据。这使得远程NVMe存储设备可以像本地设备一样高效地访问。

pcie:
PCIe(Peripheral Component Interconnect Express)是一种高速串行计算机总线标准,用于在计算机系统中连接各种硬件组件,如图形卡、存储控制器、网络适配器、声卡等。PCIe是PCI(Peripheral Component Interconnect)总线的一种演进,旨在提供更高的带宽和性能,以满足现代计算机系统对高速数据传输的需求。

高速传输:PCIe标准提供了高速数据传输通道,速度通常以“每秒传输的字节数”(GT/s)来衡量。PCIe 3.0标准支持每个通道8 GT/s的数据传输速度,而PCIe 4.0和PCIe 5.0则分别支持16 GT/s和32 GT/s的速度。这使得PCIe总线非常适合高带宽应用,如图形渲染、大规模数据存储和高性能计算。

串行连接:与传统的并行PCI总线不同,PCIe使用高速串行连接,这意味着数据以比传统PCI总线更快的速度进行传输。这种串行连接的优势包括更少的线缆、更少的电信号干扰以及更容易设计和维护。

多通道支持:PCIe支持多通道(称为“通道”或“通道数”)架构,允许多个数据通道同时传输数据,从而进一步提高总线带宽。每个通道都可以传输数据,这使得PCIe适用于并行处理任务。

多种尺寸:PCIe插槽和卡可以有不同的尺寸,以适应各种设备和应用。常见的尺寸包括x1、x4、x8和x16,它们分别表示PCIe插槽上的物理连接数量。较大的尺寸通常用于高性能图形卡和存储控制器,而较小的尺寸则用于网络适配器等设备。

热插拔支持:PCIe标准支持热插拔,这意味着用户可以在计算机运行时插入或拔出PCIe设备,而不需要关闭计算机。这提高了系统的可扩展性和可维护性。

兼容性:PCIe是一种通用标准,可用于连接各种设备,包括图形卡、存储设备、网络适配器、声卡、RAID控制器等。这种通用性使得PCIe成为连接多种硬件设备的首选总线标准。

SSD:固态硬盘(Solid State Drive,SSD)是一种高速、可靠的数据存储设备,它与传统的机械硬盘(Hard Disk Drive,HDD)相比具有许多优势。以下是有关SSD的介绍

存储技术:SSD使用闪存存储技术,这与HDD使用旋转磁盘和机械臂的工作原理截然不同。它的存储基于非易失性 NAND型闪存芯片,这些芯片可以迅速读写数据而且无需机械运动。

速度:SSD比传统HDD快得多。由于没有机械运动,SSD的读取和写入速度更高,可以大幅提高计算机的响应速度。这意味着更快的操作系统启动时间、应用程序加载速度和文件传输速度。

耐用性:由于没有机械部件,SSD更耐用。它们可以抵抗冲击和振动,而HDD在这方面较为脆弱。此外,闪存芯片的寿命通常比HDD的机械部件更长。

能耗:SSD的能耗较低。因为它们不需要花费电力来旋转磁盘或移动机械臂,所以在相同工作负载下,SSD的电能消耗更少。

向 NVMe 设备提交 I/O

NVMe 规范描述了用于与存储设备交互的硬件接口。该规范包括远程存储的网络传输定义以及本地 PCIe 设备的硬件寄存器布局。下面概述了如何通过 SPDK 将 I/O 提交到本地 PCIe 设备

NVMe 设备允许主机软件(在本例中为 SPDK NVMe 驱动程序)在主机内存中分配队列对。术语“主机”被大量使用,因此要澄清的是,这是NVMe SSD插入的系统。队列对由两个队列组成 - 提交队列和完成队列。这些队列更准确地描述为固定大小条目的圆形环。提交队列是一个由 64 字节命令结构加上 2 个整数(头和尾索引)组成的数组。完成队列同样是一个由 16 字节完成结构加上 2 个整数(头和尾索引)组成的数组。还涉及两个32位寄存器,称为门铃

通过构造一个 64 字节的命令,将其放入提交队列尾索引当前位置的提交队列中,然后将提交队列尾部的新索引写入提交队列尾部门铃寄存器,将 I/O 提交到 NVMe 设备。实际上,将整组命令复制到环中的开放插槽中,然后只写一次门铃以提交整个批次是有效的

最重要的是,命令本身描述操作,如有必要,还描述主机内存中包含与命令关联的主机内存描述符的位置。此主机内存是要写入写入命令的数据,或者是将数据放置在读取命令上的位置。使用 NVMe 设备上的 DMA 引擎将数据传输到此位置或从此位置传输数据

完成队列的工作方式类似,但设备是将条目写入环的设备。每个条目都包含一个“相位”位,该位在整个环的每个环路上在 0 和 1 之间切换。当队列对设置为生成中断时,中断包含完成队列头的索引。但是,SPDK 不启用中断,而是轮询相位位以检测完成情况。中断是非常繁重的操作,因此轮询此阶段位通常效率更高。

SPDK NVMe 驱动程序 I/O 路径

现在我们知道环形结构的工作原理,让我们介绍一下 SPDK NVMe 驱动程序如何使用它们。用户将在程序生命周期的早期时间构建一个队列对,因此这不是“热”路径的一部分。然后,他们将调用 spdk_nvme_ns_cmd_read() 等函数来执行 I/O 操作。用户提供数据缓冲区、目标 LBA 和长度,以及其他信息,例如命令的目标 NVMe 命名空间以及要使用的 NVMe 队列对。最后,用户提供一个回调函数和上下文指针,当在以后调用 spdk_nvme_qpair_process_completions() 期间发现结果命令的完成时将调用该函数和上下文指针。

驱动程序的第一阶段是分配请求对象来跟踪操作。这些操作是异步的,因此它不能简单地跟踪调用堆栈上请求的状态。在堆上分配新的请求对象会太慢,因此 SPDK 在 NVMe 队列对对象 - struct spdk_nvme_qpair 内保留一组预先分配的请求对象。分配给队列对的请求数大于 NVMe 提交队列的实际队列深度,因为 SPDK 支持几个关键的便利功能。首先是软件队列 - SPDK 将允许用户提交比硬件队列实际可以容纳的更多的请求,SPDK 将自动在软件中排队。二是分裂。SPDK 将出于多种原因拆分请求,其中一些原因将在下面概述。请求对象的数量可在队列对创建时配置,如果未指定,SPDK 将根据硬件队列深度选择一个合理的数量。

第二阶段是构建 64 字节 NVMe 命令本身。该命令内置于嵌入到请求对象的内存中,而不是直接内置到 NVMe 提交队列槽中。构造命令后,SPDK 将尝试获取 NVMe 提交队列中的开放插槽。对于提交队列中的每个元素,将分配一个称为跟踪器的对象。跟踪器在数组中分配,因此可以通过索引快速查找它们。跟踪器本身包含一个指向当前占用该插槽的请求的指针。获取特定跟踪器时,将使用跟踪器的索引更新命令的 CID 值。NVMe 规范在完成时提供了该 CID 值,因此可以通过 CID 值查找跟踪器,然后按照指针来恢复请求。

获得跟踪器(插槽)后,将处理与其关联的数据缓冲区以构建PRP列表。这本质上是一个 NVMe 分散收集列表,尽管它受到更多限制。用户向 SPDK 提供缓冲区的虚拟地址,因此 SPDK 必须执行页表查找以查找支持该虚拟内存的物理地址 (pa) 或 I/O 虚拟地址 (iova)。几乎连续的内存区域在物理上可能不是连续的,因此这可能会导致包含多个元素的 PRP 列表。有时,这可能会导致一组物理地址实际上无法表示为单个 PRP 列表,因此 SPDK 会自动透明地将用户操作拆分为两个单独的请求。有关如何管理内存的详细信息,请参阅从用户空间直接访问内存 (DMA)。

在获取跟踪器之前不构建 PRP 列表的原因是,PRP 列表描述必须在支持 DMA 的内存中分配,并且可能非常大。由于 SPDK 通常会分配大量请求,因此我们不想分配足够的空间来预构建最坏情况 PRP 列表,特别是考虑到常见情况根本不需要单独的 PRP 列表。

每个 NVMe 命令都嵌入了两个 PRP 列表元素,因此如果请求为 4KiB(或者如果它是 8KiB 并且完全对齐),则不需要单独的 PRP 列表。性能分析表明,这部分代码不是总体 CPU 使用率的主要贡献者。

填写跟踪器后,SPDK 将 64 字节命令复制到实际的 NVMe 提交队列插槽中,然后按提交队列尾门铃,告诉设备进行处理。然后,SPDK 返回到用户,而无需等待完成。

用户可以定期调用 spdk_nvme_qpair_process_completions() 以指示 SPDK 检查完成队列。具体来说,它读取下一个预期完成槽的相位位,当它翻转时,查看 CID 值以查找指向请求对象的跟踪器。请求对象包含用户最初提供的函数指针,然后调用该指针以完成命令。

spdk_nvme_qpair_process_completions() 函数将继续前进到下一个完成槽,直到完成数用完,此时它将写入完成队列头门铃,让设备知道它可以将完成队列槽用于新的完成并返回。

文章参考https://spdk.io/doc/nvme_spec.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写一封情书

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值