日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

蛋蛋读NVMe之二

發布時間:2024/1/18 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蛋蛋读NVMe之二 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上回書說道,NVMe有三寶:SQ,CQ和DB。接下來我們就詳細的看看這吉祥三寶。

Host往SQ中寫入命令, SSD往CQ中寫入命令完成結果。SQ與CQ的關系,可以是一對一的關系,也可以是多對一的關系,但不管怎樣,他們是成對的:有因就有果,有SQ就必然有CQ。

有兩種SQ和CQ,一種是Admin,另外一種是I/O,前者放Admin命令,用以Host管理控制SSD,后者放置I/O命令,用以Host與SSD之間傳輸數據?!蹦闾糁鴵?#xff0c;我牽著馬”(西游記的節奏呀),Admin SQ/CQ 和I/O SQ/CQ各司其職,你不能把Admin命令放到I/O SQ中,同樣,你也不能把I/O命令放到Admin SQ里面。如果你不信這個邪,可以不遵守這個規矩試試,看看會發生什么,反正后果自負。

正如上圖所示,系統中只有一對Admin SQ/CQ,它們是一一對應的關系;I/O SQ/CQ卻可以很多,多達65535(64K減去一個SQ/CQ)。行政人員少,干活的人多,很多公司都是這樣的吧,所以Admin SQ/CQ少,I/O SQ/CQ多就不難理解了。Host端每個Core可以有一個或者多個SQ,但只有一個CQ。給每個Core分配一對SQ/CQ好理解,為什么一個Core中還要多個SQ呢?一是性能需求,一個Core中有多線程,可以做到一個線程獨享一個SQ;二是QoS需求,什么是QoS?Quality of Service,服務質量。腦補一個場景,蛋蛋一邊看小電影,同時迅雷在后臺下載小電影,由于電腦配置差,看個小電影都卡。蛋蛋最討厭看小電影的時候卡頓了,因為你剛剛燃起的激情會被那個緩沖澆滅。所以,蛋蛋不要卡頓!怎么辦?NVMe建議,你設置兩個SQ,一個賦予高優先級,一個低優先級,把看小電影所需的命令放到高優先級的SQ,迅雷下載所需的命令放到低優先級的SQ,這樣,你那破電腦就能把有限的資源優先滿足你看小電影了。至于迅雷卡不卡,下載慢不慢,這個時候已經不重要了。能讓蛋蛋舒舒服服的看完一個小電影,就是好的QoS。

實際系統中用多少個SQ,取決于系統配置和性能需求,可靈活設置I/O SQ個數。關于系統中I/O SQ的個數,NVMe白皮書給出如下建議:

作為隊列,每個SQ和CQ都有一定的深度:對Admin SQ/CQ來說,其深度可以是2-4096(4K);對I/O SQ/CQ,深度可以是2-65536(64K)。隊列深度也是可以配置的。

SQ/CQ的個數可以配置,每個SQ/CQ的深度又可以配置,因此NVMe的性能是可以通過配置隊列個數和隊列深度來靈活調節的。NVMe太牛了吧,想胖就胖,想瘦就瘦;想高就高,想矮就矮,整一孫悟空呀!我們已經知道,AHCI只有一個命令隊列,且隊列深度是固定的32,就凡人一個,和NVMe相比,無論是在命令隊列廣度還是深度上,都是無法望其項背的;NVMe命令隊列的百般變化,更是AHCI無法做到的。說到百般變化,我突然又想到一件殘忍的事情:PCIe也是可以的。一個PCIe接口,可以有1,2,4,8,12,16,32條lane!SATA都要哭了,單挑都挑不過你,你還來群毆我。總之AHCI/SATA和NVMe/PCIe 這么一比較,畫面太美,蛋蛋不敢看。

蛋蛋在這里總是貶低AHCI/SATA,有人要說蛋蛋忘恩負義,過河拆橋。怎么說?想當年,你SSD剛出來的時候,要不是AHCI/SATA收留了你,辛苦把你養大,都不知道你現在在哪里流浪?,F在好了,你SSD翅膀硬了,不說一句感謝的話,倒反過來嫌棄我。各位看官,誤會了,前面都是演戲,不說你AHCI/SATA不好,怎么能突出我NVMe/PCIe的好,畢竟后者才是男女一號,這么做完全是劇情需要。戲外,SSD不會忘記你AHCI/SATA的好。忘恩負義?蛋蛋不是那種人。

雖然是在戲里,但總說AHCI/SATA的不好,這樣真的好嗎?蛋蛋是個懷舊的人,突然就有種蛋蛋的憂傷。好吧,以后就談NVME,不說AHCI了。孰好孰壞,留與讀者評說。

戲還得繼續演。

每個SQ放入的是命令條目,無論是Admin還是I/O命令,每個命令條目大小都是64字節;每個CQ放入的是命令完成狀態信息條目,每個條目大小是16字節。

在繼續談大寶(DB)之前,先對SQ和CQ做個小結:

SQ用以Host發命令,CQ用以SSD回命令完成狀態
SQ/CQ可以在Host的內存中,也可以在SSD中,但一般在Host 內存中(所有系列文章都是基于SQ/CQ在Host內存中講的);
兩種類型的SQ/CQ:Admin和I/O,前者發送Admin命令,后者發送I/O命令;
系統中只能有一對Admin SQ/CQ,但可以有很多對I/O SQ/CQ;
I/O SQ與CQ可以是一對一的關系,也可以是一對多的關系;
I/O SQ是可以賦予不同優先級的;
I/O SQ/CQ深度可達64K,Admin SQ/CQ深達4K;
I/O SQ/CQ的廣度和深度都可以靈活配置;
每條命令大小是64字節,每條命令完成狀態是16字節;
不要過河拆橋。

SQ/CQ中的”Q”,是Queue,隊列的意思,無論SQ還是CQ,都是隊列,并且是環形隊列。隊列有幾要素,除了隊列深度,隊列內容,還有兩個重要的,就是隊列的頭(Head)和尾巴(Tail)。大家都排過隊,你加入隊伍的時候,都是站到隊伍的最后,如果你插隊,蛋蛋就會鄙視你。隊伍最前頭的那個,正在被服務或者等待被服務,一旦完成,就離開隊伍。隊列的頭尾很重要,頭決定誰會被馬上服務,尾巴決定了新來的人站的位置。DB,就是用來記錄了一個SQ或者CQ的Head和Tail。每個SQ或者CQ,都有兩個對應的DB: Head DB和Tail DB。DB是在SSD端的寄存器,記錄SQ和CQ的頭和尾巴的位置。

上面是一個隊列的生產/消費模型。生產者往隊列的Tail寫入東西,消費者往隊列的Head取出東西。對一個SQ來說,它的生產者是Host,因為它往SQ的Tail位置寫入命令,消費者是SSD,因為它往SQ的Head取出指令執行;對一個CQ來說,剛好相反,生產者是SSD,因為它往CQ的Tail寫入命令完成信息,消費者則是Host,它從CQ的Head取出命令完成信息。

舉個例子,看圖說話.

  • 開始假設SQ1和CQ1是空的,Head = Tail = 0.

  • 這個時候,Host往SQ1中寫入了三個命令,SQ1的Tail則變成3。 Host在往SQ1寫入三個命令后,同時漂洋過海去更新SSD Controller端的SQ1 Tail DB寄存器,值為3。Host更新這個寄存器的同時,也是在告訴SSD Controller:有新命令了,需要你去取。

  • SSD Controller收到通知后,于是派人去SQ1把3個命令都取回來執行。SSD把SQ1的三個命令都消費了,SQ1的Head從而也調整為3,SSD Controller會把這個Head值寫入到本地的SQ1 Head DB寄存器。

  • SSD執行完了兩個命令,于是往CQ1中寫入兩個命令完成信息,同時更新CQ1對應的Tail DB 寄存器,值為2。SSD并且發消息給Host:有命令完成,請注意查看。

  • Host收到SSD的短信通知,于是從CQ1中取出那兩條完成信息處理。處理完畢,Host又漂洋過海的往CQ1 Head DB寄存器中寫入CQ1的head,值為2。

  • 看完這個例子,又重溫了一下命令處理流程。之前我們也許只記住了命令處理需要8步(距離曹植一步之遙),看完上面的例子,我們應該對命令處理流程有個更深入具體的認識。

    那么,DB在命令處理流程中起了什么作用呢?

    首先,如前所示,它記住了SQ和CQ的頭和尾。對SQ來說,SSD是消費者,它直接和隊列的頭打交道,很清楚SQ的頭在哪里,所以SQ head DB由SSD自己維護;但它不知道隊伍有多長,尾巴在哪,后面還有多少命令等待執行,相反,Host知道,所以SQ Tail DB由Host來更新。SSD結合SQ的頭和尾,就知道還有多少命令在SQ中等待執行了。對CQ來說,SSD是生產者,它很清楚CQ的尾巴在哪里,所以CQ Tail DB由自己更新,但是SSD不知道Host處理了多少條命令完成信息,需要Host告知,因此CQ Head DB由Host更新。SSD根據CQ的頭和尾,就知道CQ能不能以及能接受多少命令完成信息。

    DB的另外一個作用,就是通知作用:Host更新SQ Tail DB的同時,也是在告知SSD有新的命令需要處理;Host更新CQ Head DB的同時,也是在告知SSD,你返回的命令完成狀態信息我已經處理,同時表示謝意。

    這里有一個對Host不公平的地方,Host對DB只能寫,還僅限于寫SQ Tail DB和CQ Head DB,不能讀取DB。蛋蛋突然想唱首歌:

    我倆太不公平
    愛和恨全由你操縱
    可今天我已離不開你
    不管你愛不愛我

    Host就是這樣癡情。在這個限制下,我們看看Host是怎樣維護SQ和CQ的。SQ的尾巴沒有問題,Host是生產者,對新命令來說,它清楚自己應該站在隊伍哪里。但是Head呢?SSD在取指的時候,是偷偷進行的,Host對此毫不知情。Host發了取指通知后,它并不清楚SSD什么時候去取命令,取了多少命令。怎么破?機智如你,如果是你,你會怎么做?山人自有妙計。給個提示:

    這是什么鬼東西?這是SSD往CQ中寫入的命令完成狀態信息(16字節)。

    是的,SSD往CQ中寫入命令狀態信息的同時,還把SQ Head DB的信息告知了Host!!這樣,Host對SQ中Head和Tail的信息都有了,輕松玩轉SQ。

    CQ呢?Host知道Head,不知道Tail。那怎么能知道Tail呢?思路很簡單,既然你SSD知道,那你告訴我唄!SSD怎么告訴Host呢?還是通過SSD返回命令狀態信息中。哈哈,看到上圖中的“P”嗎?干什么用,做標記用。

    具體是這樣的:一開始CQ中每條命令完成條目中的”P” bit初始化為0,SSD在往CQ中寫入命令完成條目時,會把”P”寫成1。記住一點,CQ是在Host端的內存中,Host可以檢查CQ中的所有內容,當然包括”P”了。Host記住上次的Tail,然后往下一個一個檢查”P”,就能得出新的Tail了。就是這樣。

    最后,給大寶做個小結:

    DB在SSD Controller端,是寄存器
    DB記錄著SQ和CQ的Head和Tail
    每個SQ或者CQ有兩個DB: Head DB 和Tail DB
    Host只能寫DB,不能讀DB
    Host通過SSD往CQ中寫入的命令完成狀態獲取Head或者Tail
    http://www.ssdfans.com/?p=8139

    總結

    以上是生活随笔為你收集整理的蛋蛋读NVMe之二的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。