NVME(学习笔记一)—概述
NVMe概述
NVMe是一个针对基于PCIe的固态硬盘的高性能的、可扩展的主机控制器接口。
NVMe的显著特征是提供多个队列来处理I/O命令。单个NVMe设备支持多达64K个I/O 队列,每个I/O队列可以管理多达64K个命令。
当主机发出一个I/O命令的时候,主机系统将命令放置到提交队列(SQ),然后使用门铃寄存器(DB)通知NVMe设备。
当NVMe设备处理完I/O命令之后,设备将处理结果写入到完成队列(CQ),并引发一个中断通知主机系统。
NVMe使用MSI/MSI-X和中断聚合来提高中断处理的性能。
NVMe驱动概述
NVMe驱动是一个C函数库,可直接链接到应用程序从而在应用与NVMe固态硬盘之间提供直接的、零拷贝的数据传输。这是完全被动的,意味着不会开启线程,只是执行来自应用程序本身的函数调用。这套库函数直接控制NVMe设备,通过将PCI BAR寄存器直接映射到本地进程中然后执行基于内存映射的I/O(MMIO)。I/O是通过队列对(QP)进行异步提交,其一般的执行流程跟Linux的libaio相比起来,并非完全不同。
NVM Express(NVMe)是一个寄存器级接口,允许带内主机软件与NVM子系统通信。NVMe管理界面(NVMe-MI)允许管理控制器通过一个或多个外部接口与NVMe NVM子系统进行带外通信。
NVMe是一种Host与SSD之间通讯的协议
图1:NVMe管理接口协议分层

NVMe-MI利用管理组件传输协议(MCTP)作为命令传输和利用现有的MCTP SMBus / I2C和PCIe绑定物理层。
NVMe是为SSD所生的。NVMe出现之前,SSD绝大多数走的是AHCI和SATA的协议,后者其实是为传统HDD服务的。与HDD相比,SSD具有更低的延时和更高的性能,AHCI已经不能跟上SSD性能发展的步伐了,已经成为制约SSD性能的瓶颈。
跟ATA spec中定义的命令相比,NVMe的命令个数少了很多,完全是为SSD量身定制的。
NVMe有三宝:Submission Queue (SQ),Completion Queue(CQ)和Doorbell Register (DB)。 SQ和CQ位于Host的内存中,DB则位于SSD的控制器内部。上图:

SQ和CQ在Host的memory中以及DB在SSD端,上图中的NVMe Subsystem一般就是SSD。
SQ位于Host内存中,Host要发送命令时,先把准备好的命令放在SQ中,然后通知SSD来取;CQ也是位于Host内存中,一个命令执行完成,成功或失败,SSD总会往CQ中写入命令完成状态。
DB又是干什么用的呢?Host发送命令时,不是直接往SSD中发送命令的,而是把命令准备好放在自己的内存中,那怎么通知SSD来获取命令执行呢?Host就是通过写SSD端的DB寄存器来告知SSD的。
1.4架构模型
图2:单端口PCIe SSD

图3:带SMBus / I2C的双端口PCIe SSD

NVMe管理界面用于发送命令消息,该命令消息由以NVM子系统内的控制器为目标的标准NVMe管理命令组成; 用于访问NVM子系统中控制器的PCI Express配置,I / O和存储空间的命令; 和管理接口特定命令,用于清点,配置和监视NVM子系统。
图4:与单端口PCIe SSD相关的NVM子系统

图5示出了与图3中所示的PCIe SSD相对应的示例NVM子系统。NVM子系统,包含一个与PCIe端口0相关联的控制器和两个与PCIe端口1相关联的控制器。存在与每个PCIe端口相关联的管理端点和SMBus / I2C端口。由于NVM子系统包含管理端点,因此所有控制器都具有关联的控制器管理接口。
图5:与带有SMBus / I2C的双端口PCIe SSD相关的NVM子系统

管理接口请求消息和响应消息作为MCTP消息传输,消息类型通过MCTP设置为NVM Express管理消息(请参阅MCTP ID和代码规范)。 所有命令消息都源自管理控制器,并从管理端点生成响应消息。
4消息处理模型
NVMe-MI使用请求和响应处理模型。
图14:NVMe-MI MCTP消息分类

4.1 request消息
request消息是由管理控制器生成的NVMe-MI消息,用于发送给管理端点。
request消息指定管理端点要执行的操作。
4.2 reponse消息
reponse消息是管理端点完成时生成的NVMe-MI消息处理先前发出的request消息。
NVM Express基于配对的提交和完成队列机制
命令由主机软件放入提交队列。完成被放入控制器关联的完成队列。多个提交队列可以使用相同的完成队列。提交和完成队列在内存中分配。
存在管理员提交和关联的完成队列以用于控制器管理和控制(例如,创建和删除I / O提交和完成队列,中止命令,等等)。只有属于管理员命令集的命令才可以提交给管理员提交队列。
I / O命令集与I / O队列对一起使用。该规范定义了一个I / O命令集,命名为NVM命令集。主机选择一个用于所有I / O队列的I / O命令集对。
主机软件创建队列,最高可达控制器支持的最大值。通常的数量创建的命令队列基于系统配置和预期的工作负载。例如, 在基于四核处理器的系统上,每个核心可能有一个队列对,以避免锁定和确保数据结构在适当的处理器核心缓存中创建。图1提供了图形队列对机制的表示,显示提交队列和。之间的1:1映射完成队列。图2显示了多个I / O提交队列使用相同的示例核心B上的I / O完成队列。图1和图2显示了之间始终存在1:1管理员提交队列和管理员完成队列。

提交队列(SQ)是一个循环缓冲区,具有主机软件用于提交的固定插槽大小控制器执行的命令。主机软件更新相应的SQ Tail门铃当有一到n个新命令要执行时注册。之前的SQ Tail值被覆盖当有新的门铃寄存器写入时控制器。控制器按顺序提取SQ条目但是,提交队列可以按任何顺序执行这些命令。
4.1.1空队列
当Head入口指针等于Tail入口指针时,队列为Empty。图8定义了Empty队列条件。
图8:空队列定义

4.1.2满队列
当Head等于尾部时,队列为Full。队列中的条目数full比队列大小少一个。
图9定义了完整队列条件。注意:在确定队列是否为Full时,应考虑队列包装条件。
图9:完整队列定义

7控制器架构
主机软件(Host)通过预先分配的提交队列向控制器(Controller)提交命令。通过SQ Tail Doorbell寄存器写入警告控制器新提交的命令。前一个门铃寄存器值和当前寄存器写入之间的差异表示已提交的命令数。
控制器从提交队列中提取命令并将它们发送到NVM子系统进行处理。
命令处理

1.主机将一个或多个命令放置在位于内存中的提交队列(SQ)的下一个可用的槽位中执行。
2. Host用SQ尾部指针的新值去更新SQ的TailDB寄存器。这告诉了SSD控制器有一个新的命令被提交需要被处理。
3. SSD控制器将命令从SQ中转移到控制器中以供下一步执行。(从哪一个SQ中取出下一条候选命令去执行的仲裁方法,请参见4.11一节。)
4.控制器接下来执行下一条命令。命令的执行完成可能是乱序的(与提交或开始执行的时间点无关)。
5.在命令完成执行之后,SSD控制器将一个完成队列条目(CQE)放在相关的完成队列(CQ)的下一个空闲槽位中。作为CQE的一部分,SSD控制器通过修改完成条目的SQ头指针指示最新的SQE已经被消费了。每一个新的CQE都有一个从前一个条目中反转的相位标记(Phase Tag), 以向Host表明这个CQE是一个新条目。
6. SSD控制器给Host产生一个中断,以表明有一个新的CQE已经产生,可以被消费和处理了。在图中演示的是MSI-X中断,然而,中断也可以是基于PIN或者MSI的中断。注意:基于中断联合设置,可能或不能为每一个新的CQE产生一个中断。
7. Host消费和处理在CQ中放置的新的CQE。包括基于错误情况采取的任何操作。Host继续消耗和处理CQE,直到它遇到以前消费的一个条目的相位标签(Phase Tag)从当前完成队列条目(CQEs)的值中反转。
8. Host更新CQ的HeadDB寄存器,表明CQE已经被消费了。在更新相关联的CQ的HeadDB寄存器之前,Host可能消费了多个CQE。
通俗易懂的话总结一下就是:
1. Host写命令到SQ
2. Host更新SQ的TailDB, 通知SSD取命令
3. SSD收到命令,于是从SQ中取出命令
4. SSD执行命令
5. 命令执行完成后,SSD往CQ中写入命令执行结果,同时修改CQ的TailDB
6. SSD发短信通知Host命令已经执行完成
7. Host收到命令后,到CQ中查看命令完成状态
8. Host处理完CQ中的命令执行结果,更新CQ中的HeadDB, 回复SSD, "命令执行结果已经处理完毕,辛苦啦"
NVMe over PCIe和RDMA本质上都是“玩队列”。 NVMe over PCIe有两条队列,一条提交队列(SQ)和一条完成队列(CQ);而RDMA有三条队列,一条发送队列(SQ),一条接收队列(RQ)和一条完成队列(CQ),而一个SQ和一个RQ被称之为一个QP(队列对)。
对应nvme驱动代码位置:
nvme_pcie.c
1.Int nvme_pcie_qpair_submit_request()
TAILQ_INSERT_TAIL(&pqpair->outstanding_tr, tr, tq_list);
(对应app代码位置:bdev_nvme_submit_request( ) )??是吗,只是名称相近?
2. static void nvme_pcie_qpair_complete_tracker()
TAILQ_INSERT_HEAD(&pqpair->free_tr, tr, tq_list);
bdev_nvme.c
static const struct spdk_bdev_fn_table nvmelib_fn_table = { (device function table)
.destruct = bdev_nvme_destruct,
.submit_request = bdev_nvme_submit_request,
.io_type_supported = bdev_nvme_io_type_supported,
.get_io_channel = bdev_nvme_get_io_channel,
.dump_info_json = bdev_nvme_dump_info_json,
.write_config_json = bdev_nvme_write_config_json,
.get_spin_time = bdev_nvme_get_spin_time,
};
static struct spdk_bdev_module nvme_if = {
.name = "nvme",
.module_init = bdev_nvme_library_init,
.module_fini = bdev_nvme_library_fini,
.config_text = bdev_nvme_get_spdk_running_config,
.config_json = bdev_nvme_config_json,
.get_ctx_size = bdev_nvme_get_ctx_size,
};
关于MSI-X,在igb_uio.c里igbuio_msix_mask_irq( )
浅谈NVMe与MSI-X
https://blog.csdn.net/wangpeng22/article/details/78390694?locationNum=2&fps=1
https://blog.csdn.net/weijitao/article/details/46566789
http://blog.sina.com.cn/s/blog_6472c4cc0102dskj.html
NVMe制定了Host与SSD之间通讯的命令,以及命令如何执行的。
NVMe有两种命令,
一种叫Admin Command,用以Host管理和控制SSD;
另外一种就是I/O Command,用以Host和SSD之间数据的传输。下面是NVMe1.2支持的命令列表:
NVMe支持的Admin Command:

NVMe支持的I/O Command:

lib/bdev/nvme/bdev_nvme.c
_bdev_nvme_submit_request( )有IO操作的处理,
nvme_ctrlr_ut.c
test_nvme_ctrlr_init_en_1_rdy_0
test_nvme_ctrlr_init_en_1_rdy_1
test_nvme_ctrlr_init_en_0_rdy_0
test_nvme_ctrlr_init_en_0_rdy_1
test_nvme_ctrlr_init_en_0_rdy_0_ams_rr
test_nvme_ctrlr_init_en_0_rdy_0_ams_wrr
test_nvme_ctrlr_init_en_0_rdy_0_ams_vs
test_alloc_io_qpair_rr_1
test_ctrlr_get_default_ctrlr_opts
test_ctrlr_get_default_io_qpair_opts
test_alloc_io_qpair_wrr_1
test_alloc_io_qpair_wrr_2
test_spdk_nvme_ctrlr_update_firmware
test_nvme_ctrlr_fail
test_nvme_ctrlr_construct_intel_support_log_page_list
test_nvme_ctrlr_set_supported_features
test_spdk_nvme_ctrlr_doorbell_buffer_config----5 Admin Command Set
test_nvme_ctrlr_test_active_ns
nvme_ctrlr_cmd_ut.c ----- AdminCommand的功能测试集
test_get_log_pages----5 Admin Command Set
test_set_feature_cmd----5 Admin Command Set
test_set_feature_ns_cmd----5 Admin Command Set
test_get_feature_cmd----5 Admin Command Set
test_get_feature_ns_cmd----5 Admin Command Set
test_abort_cmd----5 Admin Command Set
test_io_raw_cmd
test_io_raw_cmd_with_md
test_namespace_attach----5 Admin Command Set
test_namespace_detach----5 Admin Command Set
test_namespace_create----5 Admin Command Set
test_namespace_delete----5 Admin Command Set
test_format_nvme
test_fw_commit----5 Admin Command Set
test_fw_image_download----5 Admin Command Set
转载于:NVMe协议笔记分享 - 海之心1213 - 博客园 (cnblogs.com)
NVME(学习笔记一)—概述的更多相关文章
- Struts2 学习笔记(概述)
Struts2 学习笔记 2015年3月7日11:02:55 MVC思想 Strust2的MVC对应关系如下: 在MVC三个模块当中,struts2对应关系如下: Model: 负责封装应用的状态,并 ...
- μCos-ii学习笔记1_概述
一.μCos-ii _概述 网上关于μCosii的文章多不胜数,本人学习的过程中也参考了很多人的理解和想法,看的是卢有亮老师的<嵌入式实时操作系统-μC/OS原理与实践>(第2版),同时也 ...
- MyBatis学习笔记(一) 概述
一.什么是MyBatis? MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBat ...
- Python学习笔记 - day1 - 概述及安装
Python概述 Python是一种计算机程序设计语言.我们平时已经听说过很多种流行的编程语言,比如非常难学的C语言,非常流行的Java语言,适合网页编程的JavaScript语言等等. Python ...
- XML学习笔记1——概述
我对于XML是很不够重视的,认识也是非常肤浅的,因为在之前的Web经验中,基本上都可以使用JSON来代替XML,JSON网络流量少,解析快,JS支持好等这些特点让我对自己的观点坚信不疑.然而我渐渐地改 ...
- angular2新手学习笔记(1)概述
作为培训生出生的一员.在培训出来之后如愿的找到了一份能温饱的工作.进来之后告知公司后面的项目需要angular2来搭建. 对于只会jQuery和bootstrap这两招的我来说无疑是一个巨大的挑战,在 ...
- 以太坊区块链Java(EthereumJ)学习笔记:概述
本系列文章介绍以太坊区块链基于Java语言的解决方案.通过介绍EthereumJ定义的主要模块和Class,希望为大家学习和使用EthereumJ提供一些帮助. 整体架构 以太坊的Java解决方案主要 ...
- bootstrap学习笔记 插件概述
Bootstrap插件概览 在前面布局组件章节中所讨论的组件仅仅是个开始.Bootstrap自带的12种jQuery插件,扩展了功能,可以给站点添加更多的互动.即使您不是一名高级的js开发人员, 你也 ...
- 前端学习笔记--js概述与基础语法、变量、数据类型、运算符与表达式
本篇记录js的概述与基础语法.变量.数据类型.运算符与表达式 1.概述与基础语法 2.变量 举例: 3.数据类型 4.运算符与表达式
- Java学习笔记-Java概述和环境配置
基础常识 软件:一系列按照特定顺序组织的计算机数据 和指令的集合 常见的软件: 系统软件:如:DOS,windows,Linux等 应用软件:如:扫雷,迅雷,QQ等 软件的出现实现了人与计算机之间的更 ...
随机推荐
- [转帖]小米Redis的K8s容器化部署实践
https://juejin.cn/post/6844904196924276743 背景 Why K8S How K8s Why Proxy Proxy带来的问题 K8s带来的好处 遇到的问 ...
- [转帖]配置cri-docker使kubernetes1.24以docker作为运行时
从kubernetes 1.24开始,dockershim已经从kubelet中移除,但因为历史问题docker却不支持kubernetes主推的CRI(容器运行时接口)标准,所以docker不能再作 ...
- [转帖]003、体系结构之TiKV持久化
TiKV架构和作用 数据持久化 分布式一致性 MVCC 分布式事务 Coprocessor coprocessor : 协同处理器. 可以将一些SQL计算交给TiKV处理.不需要将TiKV所有数据通过 ...
- [转帖]Jmeter学习笔记(十)——元件的作用域和执行顺序
https://www.cnblogs.com/pachongshangdexuebi/p/11582891.html jmeter是一个开源的性能测试工具,它可以通过鼠标拖拽来随意改变元件之间的顺序 ...
- [转帖]jmeter 使用beanshell 编写脚本
目录 一.介绍 1.1 介绍 1.2 下载&启动 二.jmeter中创建beanshell脚本 三.jmeter与beanshell 数据交互 3.1 例子1 beanshell 将变量传给j ...
- [转帖]一问带你掌握通过storcli做RAID
因为系统不支持直接做raid,所以需要使用storcli这个工具来操作.首先把工具上传到服务器任意目录,并使用命令chmod +x storcli64修改文件权限为可执行. 另外可通过命令ln -s ...
- 关于JVM指针压缩性能的研究
关于JVM指针压缩性能的研究 摘要 JVM的内存对消最小是 8bytes 所以32G内存的情况下可以使用 32位的指针就可以了. 32位就是4G 在乘以最小的内存extent 8 bytes 的出来可 ...
- [转帖]iptables 执行清除命令 iptables -F 要非常小心的
使用 /sbin/iptables -F 要小心,搞不好,你就马上同服务器断开连接了 以下是来自 http://wiki.ubuntu.org.cn/IptablesHowTo 上的说明 可以通过/s ...
- [转贴]BLOCKED,WAITING,TIMED_WAITING有什么区别?-用生活的例子解释
BLOCKED,WAITING,TIMED_WAITING有什么区别?-用生活的例子解释 https://www.jianshu.com/p/0976b2f23db1 https://dzone.co ...
- Redis极简教程
简介 Redis 是用C语言开发完全开源免费的,遵守BSD协议的,一个高性能的,key-value型的,NOSQL数据库. 特点 可以将内存中的数据持久化到硬盘中,重启的时候可以从硬盘中再次加载 拥有 ...