NVMe系统内存结构 - SGL

NVMe系统内存结构 - SGL

  • 1 SGL简介
  • 2 SGL Segment
  • 3 SGL Descriptor
    • 3.1 SGL Data Block descriptor
    • 3.2 SGL Bit Bucket descriptor
    • 3.3 SGL Segment descriptor
    • 3.4 SGL Last Segment descriptor
  • 4 SGL组织结构
    • 4.1 SGL1为SGL Data Block descriptor
    • 4.2 SGL1为SGL Last Segment descriptor
    • 4.3 SGL1为SGL Segment descriptor
  • 5 PRP与SGL的区别
  • 6 SGL数据读取请求示例

本文属于《 NVMe协议基础系列教程》之一,欢迎查看其它文章。

1 SGL简介

Scatter Gather List(SGL)是一个数据结构,用以描述一段数据空间,这个空间可以是数据源所在的空间,也可以是数据目标空间。

SGL首先是个List,是个链表,由一个或者多个SGL Segment组成,而每个SGL Segment又由一个或者多个SGL Descriptor组成。

2 SGL Segment

在这里插入图片描述
SGL Segment是物理内存中一个连续区域中的Qword对齐数据结构,它描述了数据缓冲区的全部、部分或没有数据缓冲区,以及指向下一个SGL Segment(如果有的话)。

一个SGL Segment由一个或多个SGL descriptor组成。只有SGL Segment中的最后一个描述符,可以是SGL Segment descriptor或SGL Last Segment descriptor。

3 SGL Descriptor

SGL Descriptor是SGL最基本的单元,它描述了一段连续的物理内存空间:起始地址+空间大小。每个SGL Descriptor大小是16字节,其通用格式定义,如下图所示:
在这里插入图片描述

  • 第14:00字节:与Descriptor类型相关,不同的类型,有不同的定义。
  • 第15字节:SGL Identifier(SGL标识符)。
    Descriptor Type Specific(03:00)- 具体定义,与Descriptor类型相关;
    SGL Descriptor Type(07:04)- 表示Descriptor类型。

SGL Descriptor Type,有如下这些,具体类型值:
在这里插入图片描述
接下来,详细介绍,每一种具体Descriptor的定义。

3.1 SGL Data Block descriptor

在这里插入图片描述
SGL Data Block descriptor描述了一个数据块,定义如下表:

BytesDescription
7:0Address:指定了数据块的64位起始内存地址。
11:8Length:指定了数据块的字节长度。
若设置为00000000h,表示没有数据传输。指定没有数据传输的SGL Data Block descriptor是一个有效的descriptor。
如果Address字段的值,加上Length字段的值,大于1_00000000_00000000h,则应当作SGL Data Block descriptor发生错误来处理。
14:12保留
15SGL Identifier:该字段的定义如下所示。
Zero(03:00)- 值为0h,如果为非0值,则视为发生错误。
SGL Descriptor Type(07:04)- 值为0h,表示SGL Data Block descriptor类型。

一个全零的SGL descriptor,是一个Address字段为00000000_00000000h,Length字段为00000000h的SGL Data Block descriptor,可以用作空descriptor。

3.2 SGL Bit Bucket descriptor

在这里插入图片描述
SGL Bit Bucket descriptor用于忽略一部分源数据(仅Host从控制器读取数据时有效),定义如下表:

BytesDescription
7:0保留
11:8Length
a)如果SGL描述了一个目标数据缓冲区,那么Length字段指定了,不传输源数据的字节数(即丢弃的字节数)。当Length字段设置为00000000h时,表示源数据不被丢弃。指定不丢弃源数据的SGL Bit Bucket descriptor是有效的descriptor。
b)如果SGL描述了一个源数据缓冲区(即,从主机内存向控制器的写操作),那么Length字段将被忽略,并且源数据或目标数据中不会丢弃任何数据。指定不丢弃数据的SGL Bit Bucket descriptor不应被视为发生错误。
c)如果支持SGL Bit Bucket descriptor,则其在目标数据缓冲区中的长度,需要被包含在NVM命令集数据传输命令中,指定的NLB (Number of Logical Blocks)参数中。它们在源数据缓冲区中的长度不被包括在NLB参数中。
14:12保留
15SGL Identifier:该字段的定义如下所示。
Zero(03:00)- 值为0h,如果为非0值,则视为发生错误。
SGL Descriptor Type(07:04)- 值为1h,表示SGL Bit Bucket descriptor类型。

3.3 SGL Segment descriptor

在这里插入图片描述
SGL Segment descriptor用于描述下一个SGL Segment,而不是最后一个SGL segment,定义如下表:

BytesDescription
7:0Address:指定了下一个SGL Segment的起始64位内存地址,这是一个SGL Segment。
11:8Length:指定了下一个SGL Segment的长度,单位为字节。Length字段,应为非零值,且为16的倍数。
如果Address字段的值,加上Length字段的值,大于1_00000000_00000000h,则应当作SGL Segment descriptor发生错误来处理。
14:12保留
15SGL Identifier:该字段的定义如下所示。
Zero(03:00)- 值为0h,如果为非0值,则视为发生错误。
SGL Descriptor Type(07:04)- 值为2h,表示SGL Segment descriptor类型。

3.4 SGL Last Segment descriptor

在这里插入图片描述
SGL Last Segment descriptor,也叫SGL末段描述符
SGL Last Segment descriptor描述了下一个和最后一个SGL Segment,定义如下表:

BytesDescription
7:0Address:指定了下一个和最后一个SGL Segment的起始64位内存地址,这是一个SGL Segment。
11:8Length:指定了下一个和最后一个SGL Segment的长度,单位为字节。Length字段,应为非零值,且为16的倍数。
如果Address字段的值,加上Length字段的值,大于1_00000000_00000000h,则应当作SGL Last Segment descriptor发生错误来处理。
14:12保留
15SGL Identifier:该字段的定义如下所示。
Zero(03:00)- 值为0h,如果为非0值,则视为发生错误。
SGL Descriptor Type(07:04)- 值为3h,表示SGL Last Segment descriptor类型。

SGL Last Segment descriptor与SGL Segment descriptor,除了SGL Descriptor Type字段值不一样,其他字段完全没有区别。

SGL Last Segment descriptor,通常作为倒数第二个SGL段描述符使用。
为什么需要把倒数第二个SGL段描述符,单独的定义成一种类型呢?
我认为是,让SSD在解析SGL的时候,碰到SGL末段描述符,就知道链表快到头了,后面只有一个段了。

4 SGL组织结构

上面讲了很多,关于SGL Segment和SGL Descriptor定义,可能大家比较迷惑,SGL结构究竟是如何组织的,接下来,我们一探究竟。

对Admin命令来说,它只能用PRP告诉SSD内存物理地址;对I/O命令(NVM Command Set)来说,除了用PRP,Host还可以用SGL的方式,来告诉SSD数据在内存中写入或者读取的物理地址。

Host在命令中会告诉SSD采用何种方式。具体来说,如果命令当中DW0[15]是0,就是PRP方式,否则就是SGL方式。

在“Command Format — NVM Command Set”命令格式定义中,[39:24]SGL Entry 1(SGL1)字段,就是该命令的第一个SGL Segment(链表的头部),如下图所示:
在这里插入图片描述
SGL1可能为三种情况:SGL Data Block descriptor、SGL Last Segment descriptor、SGL Segment descriptor,接下来,我们详细介绍。

4.1 SGL1为SGL Data Block descriptor

SGL1也就是下图中的“First SGL Segment in SQ Entry”,如下所示:
在这里插入图片描述
SGL1是一个SGL Data Block descriptor,该descriptor直接指向内存数据块,它描述了需要传输的整个数据,因此没有其他SGL Segment了。

在本例中,该命令,通过SGL1表示了1块数据。
这也是最简单的情况。

4.2 SGL1为SGL Last Segment descriptor

在这里插入图片描述
SGL1是一个SGL Last Segment descriptor,因此它是倒数第二个SGL Segment,那么它指向的SGL Segment,即为最后一个SGL Segment(图中Last SGL Segment所示)。
最后一个SGL Segment,有4个SGL Data Block descriptor,均指向数据块。

在本例中,该命令,通过SGL1表示了4块数据。

4.3 SGL1为SGL Segment descriptor

在这里插入图片描述
按上图描述,可得出如下信息:

  • SGL1是一个SGL Segment descriptor,指向第2个SGL Segment;该descriptor中Length字段,应该为6个Descriptor长度(6*16=96字节)。
  • 在第2个SGL Segment中,有5个SGL Data Block descriptor与1个SGL Last Segment descriptor,前者指向数据块,后者再指向第3个SGL Segment(最后一个SGL Segment)。
  • 在第3个SGL Segment中,有4个SGL Data Block descriptor,也是指向数据块。

在本例中,该命令,通过SGL1表示了5+4=9块数据。

如果要继续往下链接SGL Segment的话,只需要把上例中,第2个SGL Segment中最后一个descriptor换成SGL Segment descriptor类型,并保证倒数第二个SGL Segment的最后一个descriptor为SGL Last Segment descriptor类型,就可以了。

通过上述的三个例子,想必大家,已经掌握了SGL的组织结构。

5 PRP与SGL的区别

无论是PRP还是SGL,本质都是描述内存中的一段数据空间,这段数据空间在物理上,可能是连续的,也可能是不连续的。主机在命令中设置好PRP或者SGL,告诉SSD数据源在内存的什么位置,或者从闪存上读取的数据,应该放到内存的什么位置。

大家也许跟我有同样的疑问,那就是,既然有PRP,为什么还需要SGL?
事实上,NVMe1.0时候的确只有PRP,SGL是NVMe1.1之后引入的。

SGL和PRP本质区别在哪?
下图道出了真相:一段数据空间,对PRP来说,它只能映射到一个个物理页;而对SGL来说,它可以映射到,任意大小的连续物理空间。
在这里插入图片描述
SGL和PRP本质区别就是:
PRP只能描述定长的内存空间(Address),而SGL可以描述任意大小的内存空间(Address + Length),SGL更加灵活。

在支持上的区别:

  • 对NVMe over PCIe(我们目前讲的都是NVMe跑在PCIe上),Admin命令只支持PRP,I/O命令可以支持PRP或者SGL;
  • 对NVMe over Fabrics,所有命令只支持SGL。

6 SGL数据读取请求示例

这个例子中,假设Host需要从SSD中读取13KB的数据,其中真正只需要11KB数据,这11KB的数据需要放到3个大小不同的内存中,分别是:3KB,4KB和4KB。
在这里插入图片描述
有三个SGL Segment描述了,逻辑块数据在主机内存中传输的位置。

  • 这三个SGL Segment,总共包含三个Data Block descriptor,长度分别为3kb、4kb和4kb。
  • Destination SGL Segment 1,包含一个长度为2kb的Bit Bucket descriptor,它表示不传输(即忽略)来自设备的2kb的逻辑块数据,也就是读取的时候跳过这2kb数据。
  • Destination SGL Segment 1,还包含一个Last Segment descriptor,表示该描述符所指向的Segment是最后一个SGL Segment。

参考文档:

  • 蛋蛋读NVMe之三
  • 《深入浅出SSD-固态存储核心技术原理与实战》
  • 初探 NVMe
  • NVMe系列专题之四:寻址模型PRP和SGL解析
  • NVMe 1.1a 协议规范

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/326859.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【每日一题】2719. 统计整数数目-2024.1.16

题目; 2719. 统计整数数目 给你两个数字字符串 num1 和 num2 &#xff0c;以及两个整数 max_sum 和 min_sum 。如果一个整数 x 满足以下条件&#xff0c;我们称它是一个好整数&#xff1a; num1 < x < num2min_sum < digit_sum(x) < max_sum. 请你返回好整数的…

解决Windows 10/11不能连接WiFi的几种办法,可以尝试

没有什么事情比电脑无法连接到互联网更令人沮丧了。当你的Windows 10/11电脑无法连接到网络时,本文将帮助你完成一些修复。 为什么我不能连接到网络 无线网络是复杂的,因为有几个故障点。从Wi-Fi交换机到软件冲突、路由器问题和ISP问题,找出网络故障可能很困难。 Windows…

兴达易控EtherCAT转Profibus网关让工业自动化变得轻松快捷

EtherCAT转Profibus网关&#xff08;XD-ECPBM20&#xff09;是一种用于实现不同通信协议间互联互通的设备。它主要用于工业控制系统中&#xff0c;能够将EtherCAT总线的数据传输转换为Profibus网络可接受的格式。这样的网关设备在工业自动化领域有着广泛的应用&#xff0c;因为…

zds1104示波器使用指南

1、设置语言 2、功能检测验证示波器是否正常工作 3、示波器面板按钮详解 3.1、软键 3.2、运行控制与操作区 3.3、水平控制区 3.4、垂直控制区 3.5、多功能控制区 3.6、断电启动恢复&#xff0c;auto setup&#xff0c;default setup&#xff0c;恢复出厂设置详细解释 3.7、触…

UE5 RPG AttributeSet的设置

AttributeSet 负责定义和持有属性并且管理属性的变化。开发者可以子类化UAttributeSet。在OwnerActor的构造方法中创建的AttributeSet将会自动注册到ASC。这一步必须在C中完成。 Attributes 是由 FGameplayAttributeData定义的浮点值。 Attributes能够表达从角色的生命值到角色…

基于ArcGIS的晕线制作

在借助ArcGIS进行制图时&#xff0c;我们有时需要为矢量边界添加晕线&#xff0c;今天就来探索一下基于ArcGIS的晕线制作操作。 软件版本&#xff1a;ArcMap10.4.1 方法一&#xff1a;制作多环缓冲区 工具路径&#xff1a;Analysis Tools-Proximity-Mutiple Ring Buffer 思…

SUKER书客重磅发布全新系列:书客Sun立式护眼台灯,护眼养眼新境界

近日&#xff0c;国内知名的光学国货品牌——SUKER书客在2024年新品发布上&#xff0c;正式发布了全新系列的书客Sun立式护眼台灯。 SUKER书客作为近年来快速发展的创新型光学技术品牌&#xff0c;曾推出的一系列产品都取得了刷新行业标准的成绩&#xff0c;他们坚持以创新为动…

Flink启动Yarn Session报错:Couldn‘t deploy Yarn session cluster

Flink版本&#xff1a;1.1.3 启动Yarn Session的语句&#xff1a;bin/yarn-session.sh -nm test -d 报错截图如下&#xff1a; 仅通过ERROR信息只能知道是yarn session集群未能正常启动&#xff0c;因此继续向下查找&#xff1a; 找到报错信息的Caused by部分&#xff1a; 报…

[ PyQt入门教程 ] Qt Designer工具的使用

Qt Designer是PyQt程序UI界面的实现工具&#xff0c;使用Qt Designer可以拖拽、点击完成GUI界面设计&#xff0c;并且设计完成的.ui程序可以转换成.py文件供python程序调用。本文主要通过用户登录需求描述Qt Designer工具开发界面的使用方法。 主要内容 1、Qt Designer程序主界…

WEB 3D技术 three.js 3D贺卡(2) 加入天空与水面效果

上文 WEB 3D技术 three.js 3D贺卡(1) 搭建基本项目环境 我们简单搭了一个贺卡雏形 然后 我们要引入一个hdr的一个天空的效果 所以 我们需要在代码中导入 RGBELoader //导入 RGBELoader hdr工具 import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader"…

C++多线程学习[四]:多线程的通信和同步、互斥锁、超时锁、共享锁

一、多线程的状态 初始化 &#xff08;Init&#xff09;&#xff1a;该线程正在被创建。就绪 &#xff08;Ready&#xff09;&#xff1a;该线程在就绪列表中&#xff0c;等待CPU的调度。运行 &#xff08;Running&#xff09;&#xff1a;该线程正在运行。阻塞&#xff08;Bl…

用 25,000 颗星撬动一个向量数据库的世界

25,000 颗星是什么&#xff1f;是 GitHub 上对于一个数据库项目的极高认可&#xff0c;是 10,000 社区用户的共同协作&#xff0c;也是 5000 企业级用户的信赖与支持。 Milvus 用这 25,000 颗星撬动了向量数据库的世界&#xff0c;在 AGI 浪潮奔涌而来的时代&#xff0c;向全球…

Linux 内核被冬季风暴 “封印“

Linus Torvalds在内核邮件列表上宣布&#xff0c;由于他所在的美国俄勒冈州波特兰地区受到严重冬季风暴的影响&#xff0c;导致网络和电力中断。波特兰及其周边地区气温急降至零下 -10C&#xff0c;因此他不得不临时中断对Linux 6.8内核的合并窗口操作。 Linus于1月7日发布了Li…

智谱AI技术开放日:新一代基座大模型GLM-4及GLMs的发布

2024年1月16日&#xff0c;智谱AI举行了一次重要的技术开放日&#xff0c;发布了新一代基座大模型GLM-4和定制化的大模型GLMs。此次发布标志着智谱AI在人工智能领域的新一轮突破&#xff0c;进一步提升了大模型的性能&#xff0c;并降低了使用门槛&#xff0c;使得更多的人能够…

HCIP -- 第六天作业

要求&#xff1a; 实现&#xff1a; 3路由策略干涉选路&#xff1a;[R3]ip ip-prefix c permit 13.1.1.0 24 抓住13网段 [R3]route-policy c permit node 10 创建路由策略为C 序号为10 [R3-route-policy]if-match ip-prefix c 匹配路由策略c [R3-route-policy]apply cost-type…

《深入分析Linux内核源代码》读后感 --所有的进程都使用相同的逻辑地址空间,那么不同的进程是如何区分自己的数据段和代码段的呢

书中讲到从2.2版开始&#xff0c;Linux让所有的进程&#xff08;或叫任务&#xff09;都使用相同的逻辑地址空间&#xff0c;每个进程的逻辑地址空间范围为0&#xff5e;4GB&#xff0c;而且段基址也一样。那么不同的进程是如何区分自己的数据段和代码段的呢。看到另外一篇博文…

FFmpeg之AVFormat

文章目录 一、概述二、解封装流程三、重要结构体3.1、AVFormatContext3.2、AVInputFormat3.3、AVOutputFormat3.4、AVStream 四、重要函数分析4.1、avformat_alloc_context4.2、avformat_open_input4.2.1、init_input4.2.2、av_probe_input_format2 4.3、avformat_find_stream_…

RAG基础功能优化、以及RAG架构优化

RAG基础功能优化 对RAG的基础功能优化&#xff0c;我们要从RAG的流程入手[1]&#xff0c;可以在每个阶段做相应的场景优化。 从RAG的工作流程看&#xff0c;能优化的模块有&#xff1a;文档块切分、文本嵌入模型、提示工程优化、大模型迭代。下面针对每个模块分别做说明&#…

【C++】vector的使用及模拟实现

目录 一、vector的介绍及使用1.1 介绍vector1.2 vector的使用1.2.1 构造1.2.2 遍历访问1.2.3 容量空间1.2.4 增删查改 二、vector的模拟实现2.1 成员变量2.2 迭代器相关函数2.3 构造-析构-赋值重载2.3.1 无参构造2.3.2 有参构造12.3.3 有参构造22.3.4 拷贝构造2.3.5 赋值重载2.…

【线路图】 DC-DC升压恒压控制驱动芯片 2.8-40V AP8100

说明 AP8100 是一款外围电路简单的 BOOST 升压恒压控 制驱动芯片&#xff0c;适用于 2.8-40V 输入电压范围的升压恒 压电源应用领域&#xff0c;启动电压可以低至 2.5V 。 芯片会根据负载的大小自动切换 PWM &#xff0c; PFM 和 BURST 模式以提高各个负载端的…