文章目录

  • 前言
  • 1. SQ 和 CQ 是什么?
  • 2. SQ/CQ 有多少?
  • 3. SQ/CQ 如何更新
  • 4. SQ/CQ 执行流程
  • 主机和SSD如何同步队列信息?
  • 队列优先级
  • 总结

前言

NVMe(over PCIE) 的速度远超 AHCI(over SATA), 其中一个重要的原因是 NVME 的队列个数远超 AHCI。NVME 队列深度达到了64K,并且支持队列个数最大可达64K。AHCI 只有一个 Queue, Queue 深度只有32。作为NVME 重点中的重点,本文将浓墨重彩介绍命令队列SQ 和 CQ.

1. SQ 和 CQ 是什么?

NVMe定义的命令有两种: Admin Command和 IO Command。

当Host要下发Admin command时,需要一个放置Admin command的队列,这个队列就叫做Admin Submission Queue, 简称Admin SQ.

Device执行完成Admin command时,会生成一个对应的Completion回应,此时也需要一个放置Completion的队列,这个队列就叫做Admin Completion Queue,简称Admin CQ.

同样,执行IO Command时,也会有对应的两个队列,分别是IO SQ和IO CQ。

2. SQ/CQ 有多少?

NVMe Spec对Admin SQ/CQ和IO SQ/CQ有不同的约定:

只有一对Admin SQ/CQ,可以有最多 64K 对 IO SQ/CQ.

Admin SQ/CQ的队列深度是 2~4K;IO SQ/CQ的队列深度是 2~64K, 受 CAP.MQES 字段中报告的控制器支持的最大队列大小限制。

NVME 实际产品中, SQ/CQ 的数目一般是 128 组, 没有见到 64K 这么多个. 这可能是光记录这么多 SQ/CQ 信息, 也需要很多RAM 吧. 使用 128 组SQ/CQ的速度已经是绰绰有余了.


Admin SQ和CQ是一对一的,而IO SQ和CQ可以一对一,也可以多对一。

3. SQ/CQ 如何更新

Admin和IO的SQ/CQ均放在Host端Memory中;

SQ由Host来添加任务,CQ则由NVMe Controller添加信息。

SQ/CQ是队列,那就应该有队列的头(Head)和尾(Tail)。每个队列是一个先进先出的FIFO管道, 都通过一个 16 位 ID 值标识,该 ID 值在创建队列时分配给该队列。在NVMe Spec中定义SQ/CQ均是循环队列,可以理解为一个圆形(如下图上),但是内存中实际的长条状的(如下图下)。



Tail: 指向队列中的下一个空位;

Head: 指向下一个将要被执行的命令所在的位置。

随着新的消息加入到队列中来,Tail指针不停向前移动。因为内存是定常的,因此指针一旦移动到队内存的最后一个存储空间,之后再移动的话需要环回到内存的起始位置。因此内存在使用上实际上当作一个环来循环使用。

当队列为空时,Head==Tail, 尾指针和头指针指向同一位置;

当队列为满时,Head==Tail+1; 尾指针的下一个指针是头指针, 可以看出队列中有一个槽位不能使用

4. SQ/CQ 执行流程

有 SQ 发命令不就可以了,为什么还要CQ?
CQ 可以实现异步处理,这样SSD 就可以继续处理任务,而不用等到主机查看完上一个命令的处理结果。对于主机也方便,主机发完命令后便可以去做其他事情。等到空闲时再来查询CQ 里的结果。

为什么要有多个SQ/CQ 呢
有两个原因:
原因一:方便主机设置优先级
如果你一边看视频,一边在下载资源。当卡顿的时候 你一定希望看视频优先级更高。有多个SQ便是这个好处。

原因二:让 SSD 有更多的主动权去选择以一定的加权调度算法,来执行命令(比如Write SQ 执行几个Read SQ 执行几个)。

有了SQ/CQ是不是就可以执行Command了呢

参考 NVMe Spec中Command执行的流程,如下图:

在NVMe Spec中Command执行的流程有八步。

(1)Host提交新的Command。Host下发一个新Command时,将其放入Host内存中SQ;

(2)Host通知Controller提取Command。Host把Command写入SQ之后,此时Device并不知道这件事。所以,Host此时需要给Controller发信息,通知NVMe Controller:“您有新的命令请求”。这个过程通过更新在Controller内部的寄存器SQ Tail Doorbell来完成。

(3)NVMe Controller从SQ提取Command。取走Command之后,需要在Controller内部的SQ Head Pointer寄存器中更新Head所在的位置。NVMe没有规定Command存入队列的执行顺序,Controller可以一次取出多个Command进行批量处理。

(4) NVMe Controller执行从SQ提取的Commands。一个队列中的Command执行顺序是不固定的(可能导致先提交的请求后处理),这涉及到NVMe Spec定义的命令仲裁机制。执行Read/Wirte Command时,这个过程也会与Host Memory进行数据传递。

(5) NVMe Controller将Commands的完成状态写入CQ。此时,Controller需要更新CQ Tail Pointer寄存器。

(6)NVMe Controller通知Host检查Commands的完成状态。Controller通过发送一个MSI-X中断信息告知Host:“您提交的Commands,我已经执行完毕了,请您检查结果!”。

(7) Host检查CQ中的Completion信息。

(8) Host告知Controller已处理完成Completion信息。此时,Host更新Controller内部的CQ Head Doorbell。告知Controller:“您发送回来的Command执行结果,我已获知结果!”。

主机和SSD如何同步队列信息?

NVMe Command执行过程中所需的寄存器有两种:Doorbell Register和Pointer Register。Doorbell,可以简称DB,是NVMe Spec定义的寄存器;Pointer register 是主控厂商自定义的寄存器。

共四个寄存器全部放在Controller内存中。也就是说Controller知道这SQ Tail/Head和CQ Tail/Head的全部信息。

而Host仅仅知道自己更新的两个信息SQ Tail和CQ Head。

很显然,Host与Controller之间的信息是不对等的。Controller怎么把SQ Head和CQ Tail的信息告知Host呢?

Controller把SQ Head和CQ Tail的信息写入了Completion报文中。SQ Head Pointer就是SQ Head的信息。

Host 如何知道 CQ 的 Tail 位置呢? 答案是通过 Phase Tag bit.

P代表着Phase Tag bit。CQ队列中所有的位置会被初始为0, 当有新的Completion信息写入时,Phase Tag bit被置为1. Host通过读取Host 内存中CQ的Phase Tag bit信息就能判断中CQ Tail的位置。

第奇数轮(1,3,5…),Phase Tag bit 从 1 变 0 的位置,是CQ tail 位置。第偶数轮(2,4,6…), Phase 从 0 变 1 的位置, 是 CQ tail 位置。

IO command是与Admin command 的流程基本一致,主要的差别是:IO Command还会传输数据。

队列优先级

NVMe对于使用不同的队列还定义了调度策略,用于区分不同优先级的任务。其中Admin队列的优先级是最高的,IO队列可以定义绝对的优先级或Weighted round robin(WRR)的调度策略。

但这个策略还不是很完美:
在驱动中,每个CPU独占一个队列。但是如果支持按照队列的优先级来进行调度的话,则是需要按照应用层面的任务来划分队列,这两个需求是矛盾的。

无论是绝对的优先级,还是WRR都不是符合使用者直觉特别是DBA使用习惯的方式。

总结

本文介绍了NVME 重点中的重点, SQ/CQ 队列。我们分析了SQ/CQ 的基本知识和工作流程,这对我们了解host 和 SSD 的协作有很大帮助。这里只是做了一个基本的介绍,对于 SQ/CQ 的使用还有很多细节可以挖掘。

扩展阅读:
浅谈NVMe的多队列技术和IO调度

NVMe系列专题之二:队列(Queue)管理

固态硬盘:NVME 命令队列 SQ/CQ 的奥秘相关推荐

  1. 固态硬盘nvme协议什么意思 SSD四大协议传输标准

    固态硬盘nvme协议什么意思 NVMe,全称为Non-Volatile Memory Express,其中Non-Volatile Memory中文译名为非易失性存储器. Nvme协议是一种基于非易失 ...

  2. Jetson Xavier 加装固态硬盘,并将固态硬盘nvme设为为系统盘

    1. 方法一:采用sdkmanager直接把系统镜像刷机到固态硬盘 在下载完系统镜像和组件后,进行刷机那一步,storage Device一定选择NVMe,之前的老版本我印象中好像没有这个选项.选完后 ...

  3. 可乐学习NVMe之二:三只熊SQ/CQ/DB

    本文是个人学习NVMe的一个总结,借鉴网络资料https://cloud.tencent.com/developer/article/1461928和个人实践经历一共分四篇阐述NVMe. 可乐学习NV ...

  4. nvm用标准sata ahci码_老主板也能起飞——用上NVMe固态硬盘

    ↑↑↑ 点击上方 Z胖实验室 可以订阅哦 公众号的第一篇推送,就从一个很多人感兴趣的内容开始吧--NVMe固态硬盘. 最近从毕业的学长手里接过来了用了5年的台式机,CPU是i7-4690,主板是华硕B ...

  5. M.2 固态硬盘的两种类型:SATA 和 NVMe 的区别?

    参考 https://www.kingston.com.cn/cn/solutions/pc-performance/two-types-m2-vs-ssd 前言 在存储技术领域,当我们讨论 M.2 ...

  6. 270 扩展固态硬盘_新款macbook扩展坞,内置固态硬盘盒,支持NVME M2协议,一秒传输1GB...

    能内装SSD固态硬盘的扩展坞你用过吗? PX大通新款扩展坞,可装SSD固态硬盘,而且支持固态硬盘NVME协议. NVME固态硬盘扩展坞 PX大通typec扩展坞NVME固态移动硬盘盒M.2苹果笔记本m ...

  7. 华硕(ASUS)TUF GAMING B460M+intel i7 10700f+00GB SSD固态硬盘 黑苹果EFI引导文件

    硬件参数 CPU intel i7 10700f 内存 酷兽(CUSO)DDR4 16G 2666频率台式机内存条 16G 2666 * 2 硬盘 闪迪超级速500GB SSD固态硬盘 NVMe M. ...

  8. 硬盘温度70度正常吗_读懂固态硬盘:NVMe SSD的SMART健康数据这样看

    SMART在这里可不是"奔驰老头乐",它是Self-Monitoring, Analysis and Reporting Technology自我监测.分析和报告技术的缩写.通过S ...

  9. 固态硬盘的PCIE,SATA,M2,NVMe,AHCI

    [转自 https://baijiahao.baidu.com/s?id=1616207956596122967&wfr=spider&for=pc] 提纲 区别 M2和SATA SA ...

最新文章

  1. JavaScript-变量与作用域链
  2. python画统计图怎么在右上角表示哪条线代表什么_Python-matplotlib统计图之箱线图漫谈...
  3. 牛客 - 双流机场(思维)
  4. ubuntu运行navicat没有反应的解决方法
  5. 剑指offer(17)树的子结构
  6. 【软件开发底层知识修炼】三 深入浅出处理器之三 内存管理与内存管理单元(MMU)
  7. java并发编程-基础
  8. sublime配置go环境_sublime Text3配置go编译环境
  9. redies数据类型及应用场景
  10. Python案例实操1-网络爬虫
  11. 【优雅编程之道】之IO流,序列化的4点建议
  12. 龙腾世纪审判一直连接服务器,【1.7.2】【rpg】我的世界龙腾世纪群组服务器
  13. 视频格式与编码压缩标准 mpeg4,H.264.H.265 有什么关系?
  14. Java中Json解析
  15. LAMP架构 【2】
  16. 2018年总结,2019年展望!
  17. 计算机教室灭火器配置标准,学校灭火器配置标准参考
  18. Linux应用程序开发之man手册汉化+开发的简易流程说明
  19. 51CTO首届卡拉OK大赛:我唱,为欢聚而歌
  20. 让我们聊聊聊天机器人

热门文章

  1. 微信怎么@所有人?必备苹果手机小技巧
  2. AnyLogic第二讲行人仿真空间逻辑讲解
  3. Python数据结构之树形结构——数组存储
  4. 深度强化学习基础(一):RL中的基本概念
  5. 忆往昔,看今朝,望未来
  6. Jersey的配置(4)
  7. 栈的应用——数制转换
  8. 视觉SLAM十四讲学习记录 第五讲
  9. 研磨设计模式之 装饰模式-3
  10. Day1 Java读取二进制文件