前情提要:

蛋蛋读NVMe之一:为什么刘备需要NVMe

蛋蛋读NVMe之二: 吉祥三宝

有个人一直在思考三个问题:我是谁?我从哪里来?我要去哪里?

你猜这个人最后怎么着?

成了哲学家?

疯了?

疯了的哲学家?

我觉得无外乎这三种结果了。

相比人的世界,这三个问题在NVMe的世界就很容易得到答案了,至少不会把人逼疯。

我是数据,我从Host来,要到SSD去,或者,我从SSD来,要去到Host。

Host如果想往SSD上写入用户数据,需要告诉SSD写入什么数据,写入多少数据,以及数据源在内存中的什么位置,这些信息包含在Host向SSD发送的Write命令中。每笔用户数据对应着一个叫做LBA(Logical Block Address)的东西,Write命令通过指定LBA来告诉SSD写入的是什么数据。对NVMe/PCIe来说,SSD收到Write命令后,通过PCIe去Host的内存数据所在位置读取数据,然后把这些数据写入到闪存中,同时得到LBA与闪存位置的映射关系。

Host如果想读取SSD上的用户数据,同样需要告诉SSD需要什么数据,需要多少数据,以及数据最后需要放到Host内存的哪个位置上去,这些信息包含在Host向SSD发送的Read命令中。SSD根据LBA,查找映射表,找到对应闪存物理位置,然后读取闪存获得数据。数据从闪存读上来以后,对NVMe/PCIe来说,SSD会通过PCIe把数据写入到Host指定的内存中。这样就完成了Host对SSD的读访问。

在上面的描述中,大家有没有注意到一个问题,那就是Host在与SSD的数据传输过程中,Host是被动的一方,SSD是主动的一方。你Host需要数据,是我SSD主动把数据写入到你的内存中;你Host写数据,同样是我SSD主动去你Host的内存中取数据,然后写入到闪存。SSD跟快递小哥一样辛劳,不仅送货上门,还上门取件。之前蛋蛋还为Host不能读取DB打抱不平,现在看来,Host不值得同情,太懒了。

无论送货上门,还是上门取件,你都需要告诉快递小哥你的地址,不然茫茫人海,快递小哥怎么就能找到你呢?同样的,Host你不亲自传输数据,那总该告诉我SSD去你内存中什么地方取用户数据,或者要把数据写入到你内存中的什么位置。你在告诉快递小哥送货地址或者取件地址时,会说XX路XX号XX弄XX楼XX室,也可能会说XX小区XX楼XX室,anyway,快递小哥能找到就行。Host也有两种方式来告诉SSD数据所在内存位置,一是PRP (Physical Region Page, 不是P2P!),二是SGL (Scatter/Gather List)。不过,后者感觉不怎么友善,因为怎么听起来都像”死过来”(SGL)。当然了,也可能是我误会了,人家只是在说”送过来”。

先说PRP。

NVMe把Host的内存划分为一个一个页(Page),页的大小可以是4KB,8KB,16KB… 128MB。

PRP是什么,长什么样呢?

PRP Entry本质就是一个64位内存物理地址,只不过把这个物理地址分成两部分:页起始地址和页内偏移。最后两bit是0,说明PRP表示的物理地址只能四字节对齐访问。页内偏移可以是0,也可以是个非零的值。

PRP Entry描述的是一段连续的物理内存的起始地址。如果需要描述若干个不连续的物理内存呢?那就需要若干个PRP Entry。把若干个PRP Entry链接起来,就成了PRP List。

是的,正如你所见,PRP List中的每个PRP Entry的偏移量都必须是0,PRP List中的每个PRP Entry都是描述一个物理页。它们不允许有相同的物理页,不然SSD往同一个物理页写入几次的数据,导致先写入的数据被覆盖。

每个NVMe命令中有两个域:PRP1和PRP2,Host就是通过这两个域告诉SSD数据在内存中的位置或者数据需要写入的地址。

PRP1和PRP2有可能指向数据所在位置,也可能指向PRP List。类似C语言中的指针概念,PRP1和PRP2可能是指针,也可能是指针的指针,还有可能是指针的指针的指针。别管你包的有多严实,根据不同的命令,SSD总能一层一层的剥下包装,找到数据在内存的真正物理地址。SSD善解人衣。

下面是一个PRP1指向PRP List的示例:

PRP1指向一个PRP List,PRP List位于Page 200,页内偏移50的位置。SSD确定PRP1是个指向PRP List的指针后,就会去Host内存中(Page 200,Offset 50)把PRP List取过来。获得PRP List后,就获得数据的真正物理地址,SSD然后就会往这些物理地址读入或者写入数据。

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

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

SGL是什么?SGL是一个数据结构,用以描述一段数据空间,这个空间可以是数据源所在的空间,也可以是数据目标空间。SGL(Scatter Gather List)首先是个List,是个链表,由一个或者多个SGL Segment组成,而每个SGL Segment又由一个或者多个SGL Descriptor组成。SGL Descriptor是SGL最基本的单元,它描述了一段连续的物理内存空间:起始地址+空间大小。

每个SGL Descriptor大小是16字节。一块内存空间,可以用来放用户数据,也可以用来放SGL Segment,根据这段空间的不同用途,SGL Descriptor也分几种类型。

有4种SGL Descriptor,一种是Data Block,这个好理解,就是描述的这段空间是用户数据空间;一种是Segment描述符。SGL不是由SGL Segment组成的链表吗?既然是链表,前面一个Segment就需要有个指针指向下一个Segment,这个指针就是SGL Segment描述符,它描述的是它下个Segment所在的空间。特别地,对链表当中倒数第二个Segment,它的SGL Segment描述符我们把它叫做SGL Last Segment描述符。它本质还是SGL Segment描述符,描述的还是SGL Segment所在的空间。为什么需要把倒数第二个SGL Segment描述符单独的定义成一种类型呢?我认为是让SSD在解析SGL的时候,碰到SGL Last Segment描述符,就知道链表快到头了,后面只有一个Segement了。那么,SGL Bit Bucket是什么鬼?它只对Host读有用,用以告诉SSD,你往这个内存写入的东西我是不要的。好吧,你既然不要,我也就不传了。

说了这么多,可能有点晕,结合下张图,可能会更明白点。

如果还是晕,看个例子吧。

这个例子中,假设Host需要往SSD中读取13KB的数据,其中真正只需要11KB数据,这11KB的数据需要放到3个大小不同的内存中,分别是:3KB,4KB和4KB。

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

大家也许跟我有个同样的疑问(自作多情?),那就是,既然有PRP,为什么还需要SGL?事实上,NVMe1.0的时候的确只有PRP,SGL是NVMe1.1之后引入的。看看SGL和PRP有什么不同。SGL不仅提供了一个内存基地址,还提供了该段内存的大小信息(length),PRP只提供了一个基地址,内存大小需要SSD根据命令上下文去猜;SGL可描述任意的内存空间,相对PRP来说更灵活,后者基本按页访问内存;另外SGL提供了一个Bit Bucket的东西,一段连续的LBA空间,其中的一些数据我可以不需要传输,PRP好像做不到这点。

这章就到这吧。下面《蛋蛋读NVMe之四》,蛋蛋会带大家走基层,看看一个NVMe读写命令在PCIe层是怎样实现的。精彩继续,不要错过。

本文转载来自SSD技术学习网,本文地址:http://www.ssdfans.com/?p=1177

房市静心贴:蛋蛋读NVMe之三相关推荐

  1. nvme命令中prp_蛋蛋读NVMe之三

    有个人一直在思考三个问题:我是谁?我从哪里来?我要去哪里? 你猜这个人最后怎么着? 成了哲学家? 疯了? 疯了的哲学家? 我觉得无外乎这三种结果了. 相比人的世界,这三个问题在NVMe的世界就很容易得 ...

  2. 蛋蛋读UFS之三:UFS数据包UPIU

    转自:蛋蛋读UFS之三:UFS数据包UPIU UFS中流淌的数据包叫做UPIU(UFS Protocol Information Unit,UFS协议信息单元),它是固定格式的数据结构,用以传输应用层 ...

  3. 蛋蛋读NVMe之二: 吉祥三宝

    蛋蛋读NVMe之一:为什么刘备需要NVMe 上回书说道,NVMe有三宝:SQ,CQ和DB.接下来我们就详细的看看这吉祥三宝. Host往SQ中写入命令, SSD往CQ中写入命令完成结果.SQ与CQ的关 ...

  4. 蛋蛋读UFS之二:UFS协议栈

    转自:蛋蛋读UFS之二:UFS协议栈 任何一种接口或者协议,都是由一个完整的协议栈组成的.UFS也不例外. UFS定义了一个完整的协议栈.从上到下,依次为应用层.传输层.数据链路层和物理层.UFS使用 ...

  5. 蛋蛋读UFS之一:UFS简介

    转载:蛋蛋读UFS之一:UFS简介 我们知道,我们电脑由三大件组成:CPU,内存和硬盘.CPU用以计算和控制,内存用以临时存储程序运行时所需的数据(掉电数据丢失),而硬盘用以长久保存数据(掉电数据不丢 ...

  6. 蛋蛋读UFS之九:UFS数据安全

    转自:蛋蛋读UFS之九:UFS数据安全 前面提到RPMB使用认证机制和抗重放攻击机制保障数据不被黑客攻击,除此之外,UFS还有其它一些手段来保护用户数据安全,这一章节我们来关注UFS数据安全. UFS ...

  7. 蛋蛋读UFS之六:UFS设备初始化和启动

    转自:蛋蛋读UFS之六:UFS设备初始化和启动 这一节讲讲UFS初始化. 初始化和启动包括三个阶段:部分初始化,加载启动代码(可选)和初始化完成. 部分初始化阶段 这个阶段开始于上电或者设备重启,它涉 ...

  8. 蛋蛋读UFS之十:UFS电源管理

    转自:蛋蛋读UFS之十:UFS电源管理 UFS是手机存储设备,因此对功耗要求很高.我们来看看UFS的电源管理. 三个供电电压,VCC,VCCQ和VCCQ2,分别给UFS设备模块供电.UFS设备主要包括 ...

  9. 可乐学习NVMe之三:解读PRP/SGL

    原文来自https://cloud.tencent.com/developer/article/1458759,前两个章节解释了总体框架和命令分析. NVMe学习之一:为什么SSD需要NVMe? NV ...

最新文章

  1. AI颠覆经济世界作用被夸大?影响远比媒体头条报道更加复杂
  2. java手机游戏模拟器下载_Java手机游戏模拟器
  3. python【Matlibplot绘图库】画图种类(真の能看懂~!)
  4. NYOJ 620 真实的谎言
  5. dbcc dbreindex server sql_DBCC DBREINDEX重建索引提高SQL Server性能
  6. 完美解决ArcGIS10.2和Erdas9.2软件冲突的方法:共存!
  7. 简单谈谈haskell
  8. 武汉涉密信息系统集成资质介绍
  9. 标竿学习 - 一项有效的管理工具(转载)
  10. 一、首页、详情页、文章编辑页制作《iVX低代码/无代码个人博客制作》
  11. 搭建自己的代理服务器
  12. python解析mht文件_php解析mht文件转换成html
  13. ZOJ3987(二进制枚举+java大数)
  14. curaengine linux编译,CuraEngine_vs-master 在vs编译的curaengine - 下载 - 搜珍网
  15. 大厂社区、知名技术博主,学习连接看这里,全!!!
  16. 独立开发者为什么不需要运营也能月薪几万,甚至几十万?
  17. mysql中修改表字段名/字段长度/字段类型详解
  18. linux发行版中的i386/i686/x86-64/有什么区别?
  19. Maven 创建 Spring、SpringMVC、Mybatis(SSM)项目
  20. centos7错误:can‘t create 事务 lock on /var/lib/rpm/.rpm.lock (权限不够)切换root用户

热门文章

  1. fabric基本概念
  2. 智能汽车进入3.0时代,双目立体视觉「打通」智驾与底盘
  3. 抽象abstract和接口详解
  4. Excel只复制有公式的单元格进行批量的求和操作
  5. 最新安徽安全员B考试判断题预测题库
  6. win7 tcp/ip4属性按钮灰色,无法修改IP的解决方案
  7. 对一个加壳的可执行文件进行脱壳三种方法
  8. wordpress地图_如何在WordPress中嵌入必应地图
  9. 2017中石计算机网络基础试题答案,石大远程2017春计算机网络原理(含模拟实验)作业三...
  10. Java、JSP等数码产品在线销售系统