任何新技術的出現都是為了解決當前情況存在的問題。NVMe的出現也是為了解決當前存在的問題。這個問題就是日益快速增長的存儲介質性能與傳輸通道性能太差之間的矛盾。基于SSD的存儲設備性能都要上天了,但SAS和SATA接口的性能卻沒有本質的提升。
目前基于SCSI協議的SAS和SATA只能是單個隊列而且每個隊列的深度也比較低,分別是254和32的隊列深度。而NVMe協議設計之初就考慮了該問題,它的***隊列數量可以是64K(65535個命令隊列和1個管理隊列),而每個隊列的深度可以高達64K。與SCSI協議相比,就好比一個鄉村的羊腸小路和一個雙向八車道的高速公路的差別。
圖1 美麗的鄉村下路和京港澳高速
NVMe基本原理
為了便于理解主機和NVMe設備的關系,我們這里簡化NVMe設備的內部結構。如圖2所示為NVMe白皮書中的配圖,這里主機稱為Host,而NVMe設備稱為Controller(控制器)。主機和控制器之間通過共享內存的隊列實現交互。
圖2 NVMe多隊列示意圖
NVMe的隊列分為2種,其中一種是用于管理的隊列,稱為Admin Queue(管理隊列),僅有一個,另外一種是命令隊列(Command Queue),最多可以有65535個。其中命令隊列的數量和模式都是通過管理隊列來設置的。其中每一個隊列實際上是一個隊列對,也就是包括兩個隊列,分別是提交隊列(Submission Queue)和完成隊列(Completion Queue)。提交隊列用于主機端向NVMe設備發送NVMe命令,而完成隊列則用于NVMe設備向主機反饋命令執行情況。實際上NVMe還有另外一種模式,就是多個提交隊列共享同一個完成隊列的情況,本文暫時不做介紹。
NVMe隊列及命令的處理流程
上文我們知道NVMe是通過隊列傳遞控制命令和命令等內容的,那么這里的隊列實體到底是什么呢?其實這里提交隊列和完成隊列就是內存的一個區域。在數據結構原理上這里的隊列其實是一個環形緩沖區,如圖3所示。
圖3 環形緩沖區
NVMe通過一種門鈴機制(Doorbell)來告知控制器命令隊列是否有新數請求/命令。也就是說每個隊列都有一個門鈴指針。對于發送隊列來說,這個指針表示的是發送隊列的尾指針。主機端將數據寫入到發送隊列后,更新映射到位于設備寄存器空間中的門鈴的尾指針。此時,在控制器端就知道有新的請求/命令到來,接下來就可以進行對其進行處理。
當控制器完成一個NVMe請求時,通過完成隊列來把完成的結果告知主機端。與發送隊列不同,完成隊列是通過中斷機制(可以是INTx,MSI或MSIx)告訴主機端。如圖4是一個命令的完整處理流程。
圖4 命令處理完整流程
NVMe的命令格式
前面我們介紹了命令的發送和處理流程,接下來我們看看NVMe的命令長什么樣。如圖5是NMVe命令的具體格式,如果大家了解TCP/IP協議或者SCSI協議,那么理解本圖將相當容易。在圖4中每一行為8個字節,命令大小總共為64字節。
圖5 NVMe的命令格式
在這個命令格式中有幾個字段本身是比較復雜的,限于篇幅,且不打算讓大家看完本文后頭疼,本文不打算介紹所有細節。本文簡單的介紹一下該命令格式的幾個關鍵字段。其中Command Identifier標識一個具體的命令。Namespace Identifier則表示命令發送到那個命名空間。Data Pointer 1 和Data Pointer 2則用于標識數據的具體位置。
這里有兩點需要說明:
NVMe的一個控制器下面可以有多個命名空間(Namespace),通過Namespace ID來標識的。
命令與數據是分離的,并不像TCP那樣數據在命令后面。
我們這里重點介紹一下Command Identifier,該字段占用4個字節的空間。雖然僅有4個字節,但有分為3大部分,6小部分,具體如圖6所示。
圖6 命令標識格式
我們以從低位到高位的順序分別介紹一下各個字段的含義:
OPC: 全稱為Opcode,也就是被執行命令的操作碼。具體來說就是想讓控制器干什么,比如讀數據、寫數據或者刷寫等。
圖7 OPC定義
FUSE: 全稱為Fused Operation, 用于標識該命令是普通命令還是復合命令。如圖8是白皮書對該字段的說明。
圖8 FUSE的定義
PSDT: 全稱為PRP or SGL for Data Transfer,這個用于說明存儲數據的內存的組織形式。
NVMe的性能
***我們看一下NVMe與SAS和SATA存儲設備的性能對比。為了避免廣告嫌疑,本文就布局圖說明設備的廠商和類型了。
圖9 性能對比
通過上圖可以清楚的看到SAS和SATA設備與NVMe設備的性能差異,特別是對于讀操作,NVMe有絕對的性能優勢。
來源:itworld123 (SunnyZhang)
評論
查看更多