編者按
軟件和硬件,既相互依存又需要某種程度上的相互獨(dú)立。通過(guò)軟件和硬件之間的接口把兩者連接在一起。軟硬件接口,有很多含義:比如指令集是CPU軟件和硬件之間的接口;比如一些硬件模塊(包括IO接口模塊、GPU、各種加速引擎等)暴露出來(lái)的可讀寫(xiě)寄存器,則為控制接口;再比如,CPU和GPU或其他硬件模塊之間通過(guò)DMA進(jìn)行數(shù)據(jù)交互的(軟硬件間的)數(shù)據(jù)傳輸接口。 軟硬件接口,是個(gè)非常龐大的命題。本文是《軟硬件融合》圖書(shū)內(nèi)容的節(jié)選,聚焦在軟件和硬件之間的數(shù)據(jù)交互接口。
軟件和硬件之間數(shù)據(jù)交互接口
我們?cè)谟?jì)算機(jī)的基礎(chǔ)課程里一般都學(xué)過(guò)IO交互的四種模式:寄存器模式、中斷模式、DMA模式和通道模式。隨著計(jì)算機(jī)技術(shù)的發(fā)展,除了IO設(shè)備,還有很多獨(dú)立的硬件組件通過(guò)各種類(lèi)型總線跟CPU連接在一起。接口已經(jīng)不僅僅是用于IO數(shù)據(jù)傳輸場(chǎng)景,也用于軟件(運(yùn)行于CPU的程序)和其他硬件之間的數(shù)據(jù)交互場(chǎng)景。 注:本文用“軟硬件接口”特指軟件和硬件之間數(shù)據(jù)交互的接口。
1 軟硬件接口定義
傳統(tǒng)的非硬件緩存一致性總線,是需要軟件驅(qū)動(dòng)顯式的控制設(shè)備來(lái)進(jìn)行數(shù)據(jù)交互的。通過(guò)梳理軟硬件接口的演進(jìn),逐步給出軟硬件接口的定義。 a. 軟硬件接口演進(jìn)
(a) CPU輪詢? ? ? ? ? ? ? ? ? ?(b) CPU中斷???? ?? ? ? ???? ? (c) DMA方式
(d) 共享隊(duì)列??? ? ? ???? ???
(e) 用戶態(tài)輪詢???? ?? ? ? ??? ?
(f) 多隊(duì)列 圖1 軟硬件接口的演進(jìn) 軟硬件接口是在IO接口基礎(chǔ)上的擴(kuò)展,如圖1,我們結(jié)合IO交互的四種模式,重新梳理一下軟硬件接口的演進(jìn):
第一階段,使用軟件輪詢硬件狀態(tài)。如圖1(a),最開(kāi)始是通過(guò)軟件輪詢,這時(shí)候軟件和硬件的交互非常簡(jiǎn)單。發(fā)送的時(shí)候,軟件會(huì)定期的去查詢硬件的狀態(tài),當(dāng)發(fā)送緩沖為空的時(shí)候,就把數(shù)據(jù)寫(xiě)入到硬件的緩存寄存器;接收的時(shí)候,軟件會(huì)定期的查詢硬件的狀態(tài),當(dāng)接收緩沖區(qū)有數(shù)據(jù)的時(shí)候,就把數(shù)據(jù)讀取到軟件。
第二階段,使用中斷模式。如圖1(b),隨著CPU的性能快速提升,統(tǒng)計(jì)發(fā)現(xiàn),輪詢的失敗次數(shù)很高,大量的CPU時(shí)間被浪費(fèi)在硬件狀態(tài)查詢而不是數(shù)據(jù)傳輸,因此引入中斷模式。只有當(dāng)發(fā)送緩沖存在空閑區(qū)域可以讓軟件存放一定量待發(fā)送數(shù)據(jù)的時(shí)候,或者接收緩沖已經(jīng)有一定量數(shù)據(jù)待軟件接收的時(shí)候,硬件會(huì)發(fā)起中斷,CPU收到中斷后進(jìn)入中斷服務(wù)程序,在中斷服務(wù)程序里處理數(shù)據(jù)的發(fā)送和接收。
第三階段,引入DMA。如圖1(c),前面的兩種情況下,都需要CPU來(lái)完成數(shù)據(jù)的傳輸,依然會(huì)有大量的CPU消耗。因此引入了專(zhuān)用的數(shù)據(jù)搬運(yùn)模塊DMA來(lái)完成CPU和硬件之間的數(shù)據(jù)傳輸,某種程度上,DMA可以看做是用于代替CPU進(jìn)行數(shù)據(jù)搬運(yùn)的加速器。發(fā)送的時(shí)候,當(dāng)數(shù)據(jù)在CPU內(nèi)存準(zhǔn)備好,CPU告訴DMA源地址和數(shù)據(jù)的大小,DMA收到這些信息后主動(dòng)把數(shù)據(jù)從CPU內(nèi)存搬到硬件內(nèi)部。同樣的,接收的時(shí)候,CPU開(kāi)辟好一片內(nèi)存空間并告知DMA目標(biāo)地址和空間的長(zhǎng)度,DMA負(fù)責(zé)把硬件內(nèi)部的數(shù)據(jù)搬運(yùn)到CPU內(nèi)存。
第四階段,專(zhuān)門(mén)的共享隊(duì)列。如圖1(d),引入了DMA之后,如果只有一片空間用于軟件和硬件之間的數(shù)據(jù)交換,則軟件和硬件之間的數(shù)據(jù)交換則是同步的。例如在接收的時(shí)候,當(dāng)DMA把數(shù)據(jù)搬運(yùn)到CPU內(nèi)存之后,CPU需要馬上進(jìn)行處理并釋放內(nèi)存,CPU處理的時(shí)候DMA則只能停止工作。后來(lái)引入了乒乓緩沖的機(jī)制,當(dāng)一個(gè)內(nèi)存緩沖區(qū)用于DMA傳輸數(shù)據(jù)的時(shí)候,另一個(gè)緩沖區(qū)的數(shù)據(jù)由CPU進(jìn)行處理,實(shí)現(xiàn)DMA傳輸和CPU處理的并行。更進(jìn)一步的,演變成更多緩沖區(qū)組成的循環(huán)緩沖隊(duì)列。這樣,CPU的數(shù)據(jù)處理和DMA的數(shù)據(jù)傳輸則完全異步的完成,并且CPU對(duì)數(shù)據(jù)的處理以及DMA對(duì)數(shù)據(jù)的搬運(yùn)都可以批量操作完成后,再同步狀態(tài)信息給對(duì)方。
第五階段,用戶態(tài)的軟件輪詢共享隊(duì)列驅(qū)動(dòng)。如圖1(e),進(jìn)一步的,隨著帶寬和內(nèi)存的增加,導(dǎo)致數(shù)據(jù)頻繁的在用戶態(tài)應(yīng)用程序、內(nèi)核的堆棧、驅(qū)動(dòng)以及硬件之間交互,并且緩沖區(qū)也越來(lái)越大,這些都不可避免的增加系統(tǒng)消耗,并且?guī)?lái)更多的延遲;而且,數(shù)據(jù)交互頻繁,導(dǎo)致的中斷的開(kāi)銷(xiāo)也是非常龐大的。因此,通過(guò)用戶態(tài)的PMD(Polling Mode Driver,輪詢模式驅(qū)動(dòng))可以高效的在硬件和用戶態(tài)的應(yīng)用程序直接傳遞數(shù)據(jù),不需要中斷,完全繞開(kāi)內(nèi)核,以此來(lái)提升性能和降低延遲。
第六階段,支持多隊(duì)列。如圖1(f),隨著硬件設(shè)計(jì)規(guī)模擴(kuò)大,硬件資源越來(lái)越多,在單個(gè)設(shè)備里,可以通過(guò)多隊(duì)列的支持,來(lái)提高并行性。驅(qū)動(dòng)也需要加入對(duì)多隊(duì)列的支持,這樣我們甚至可以為每個(gè)應(yīng)用程序配置專(zhuān)用的隊(duì)列或隊(duì)列組,通過(guò)多隊(duì)列的并行性來(lái)提升性能和應(yīng)用數(shù)據(jù)的安全性。
說(shuō)明:本小節(jié)所講的內(nèi)容,主要是基于傳統(tǒng)的非緩存一致性總線的數(shù)據(jù)交互演進(jìn)。隨著跨芯片的緩存數(shù)據(jù)一致性總線開(kāi)始流行,通過(guò)硬件完成數(shù)據(jù)交互,在提升性能的同時(shí),也簡(jiǎn)化了軟件設(shè)計(jì)。 b. 軟硬件接口的組成部分 粗略的說(shuō),軟硬件接口是由驅(qū)動(dòng)(Driver)和設(shè)備(Device)組成,驅(qū)動(dòng)和設(shè)備的交互也即軟件和硬件的交互。更確切一些的說(shuō),軟硬件接口包括交互的驅(qū)動(dòng)軟件、硬件設(shè)備的接口部分邏輯,也包括內(nèi)存中的共享隊(duì)列,還包括傳輸控制和數(shù)據(jù)信息的總線。
圖2軟硬件接口硬件架構(gòu)示意模型 如圖2,是軟硬件接口硬件架構(gòu)的示意模型。軟硬件接口的組件詳細(xì)介紹如下:
驅(qū)動(dòng)軟件。驅(qū)動(dòng)是提供一定的接口API,讓上層的軟件能夠更加方便的與硬件交互。驅(qū)動(dòng)負(fù)責(zé)硬件設(shè)備控制面的配置、運(yùn)行控制以及設(shè)備數(shù)據(jù)面的數(shù)據(jù)傳輸控制等。驅(qū)動(dòng)屏蔽硬件的接口細(xì)節(jié),對(duì)上層軟件提供標(biāo)準(zhǔn)的API函數(shù)接口。驅(qū)動(dòng)屏蔽硬件細(xì)節(jié),提供標(biāo)準(zhǔn)API給上層軟件,在單機(jī)系統(tǒng)是非常有價(jià)值的。通過(guò)不同版本的驅(qū)動(dòng),既可以屏蔽硬件細(xì)節(jié),又可以跟不同的操作系統(tǒng)平臺(tái)兼容。在云計(jì)算場(chǎng)景,要求要更嚴(yán)格一些,云場(chǎng)景期望是完全標(biāo)準(zhǔn)的硬件接口。驅(qū)動(dòng)是代表軟件與硬件交互的接口,但依然是軟件的一部分,在云計(jì)算虛擬機(jī)驅(qū)動(dòng)也會(huì)遷移到新的環(huán)境,這就要求新的運(yùn)行環(huán)境和原始環(huán)境一致。也就是說(shuō),在IO直通模式下,需要雙方的硬件接口本身就是一致的。
設(shè)備硬件接口子模塊,包括DMA和內(nèi)部緩沖。高速的設(shè)備一般都有專(zhuān)用的DMA,專(zhuān)門(mén)負(fù)責(zé)數(shù)據(jù)搬運(yùn)。驅(qū)動(dòng)會(huì)通知DMA共享隊(duì)列狀態(tài)信息,然后DMA會(huì)讀取內(nèi)存中的共享隊(duì)列描述符,并根據(jù)描述符信息負(fù)責(zé)在CPU內(nèi)存和內(nèi)部緩沖之間搬運(yùn)數(shù)據(jù)。
共享隊(duì)列。特定的跟硬件DMA格式兼容的共享隊(duì)列數(shù)據(jù)結(jié)構(gòu),軟件和硬件通過(guò)共享隊(duì)列交互數(shù)據(jù)。每個(gè)共享隊(duì)列包括隊(duì)列的頭和尾指針、組成隊(duì)列的各個(gè)描述符項(xiàng)以及每個(gè)描述符項(xiàng)所指向的實(shí)際的數(shù)據(jù)塊。共享隊(duì)列位于軟件側(cè)的CPU內(nèi)存里,由軟件驅(qū)動(dòng)負(fù)責(zé)管理。
傳輸?shù)目偩€:軟硬件交互可以說(shuō)是上層功能,需要底層接口總線的承載。例如,在片內(nèi)通常是通過(guò)AXI-Lite總線來(lái)實(shí)現(xiàn)軟件對(duì)硬件的寄存器讀寫(xiě)控制,而數(shù)據(jù)總線則是通過(guò)AXI實(shí)現(xiàn)硬件DMA對(duì)軟件的CPU內(nèi)存的讀寫(xiě)訪問(wèn)。芯片間的總線常見(jiàn)的主要是PCIe,通過(guò)PCIe的TLP包來(lái)承載上層的各種類(lèi)型的讀寫(xiě)訪問(wèn)。
2 生產(chǎn)者消費(fèi)者模型
生產(chǎn)者消費(fèi)者問(wèn)題(Producer-Consumer Problem)是多進(jìn)程同步問(wèn)題的經(jīng)典案例之一,描述了共享固定大小緩沖區(qū)的兩個(gè)進(jìn)程,即所謂的“生產(chǎn)者”和“消費(fèi)者”,在實(shí)際運(yùn)行時(shí)如何處理交互的問(wèn)題。 如圖3所示,生產(chǎn)者的主要作用是生成一定量的數(shù)據(jù)放到緩沖區(qū)中,然后重復(fù)此過(guò)程。與此同時(shí),消費(fèi)者也在緩沖區(qū)消耗這些數(shù)據(jù)。問(wèn)題的關(guān)鍵就是要保證生產(chǎn)者不會(huì)在緩沖區(qū)滿時(shí)加入數(shù)據(jù),消費(fèi)者不會(huì)在緩沖區(qū)中空時(shí)消耗數(shù)據(jù)。
圖3 經(jīng)典生產(chǎn)者消費(fèi)者模型 解決問(wèn)題的基本辦法是:讓生產(chǎn)者在緩沖區(qū)滿時(shí)休眠,等到消費(fèi)者消耗緩沖區(qū)中的數(shù)據(jù),從而緩沖區(qū)有了空閑區(qū)域的時(shí)候,生產(chǎn)者才能被喚醒,開(kāi)始繼續(xù)往緩沖區(qū)添加數(shù)據(jù);同樣,也需要讓消費(fèi)者在緩沖區(qū)空時(shí)進(jìn)入休眠,等到生產(chǎn)者往緩沖區(qū)添加數(shù)據(jù)之后,再喚醒消費(fèi)者繼續(xù)消耗數(shù)據(jù)。 a. 進(jìn)程間通信 一個(gè)生產(chǎn)者進(jìn)程,一個(gè)消費(fèi)者進(jìn)程,生產(chǎn)者進(jìn)程通過(guò)共享緩沖傳遞數(shù)據(jù)給消費(fèi)者進(jìn)程。如果程序員不夠小心,沒(méi)有考慮多進(jìn)程間相互影響的話,很可能寫(xiě)出下面這段會(huì)導(dǎo)致“死鎖”的代碼。
// 該算法使用了兩個(gè)系統(tǒng)庫(kù)函數(shù):sleep 和 wakeup。 // 調(diào)用 sleep的進(jìn)程會(huì)被阻斷,直到有另一個(gè)進(jìn)程用wakeup喚醒之。 // 代碼中的itemCount用于記錄緩沖區(qū)中的數(shù)據(jù)項(xiàng)數(shù)。 int?itemCount?=?0; procedure producer() { while (true) { item = produceItem(); if (itemCount == BUFFER_SIZE) { sleep(); } putItemIntoBuffer(item); itemCount = itemCount + 1; if (itemCount == 1) { wakeup(consumer); } } } procedure consumer() { while (true) { if (itemCount == 0) { sleep(); } item = removeItemFromBuffer(); itemCount = itemCount - 1; if (itemCount == BUFFER_SIZE - 1) { wakeup(producer); } consumeItem(item); } }上面代碼中的問(wèn)題在于它可能導(dǎo)致競(jìng)爭(zhēng)條件,進(jìn)而引發(fā)死鎖。考慮下面的情形:
消費(fèi)者進(jìn)程把最后一個(gè)itemCount的內(nèi)容讀出來(lái)(注意它現(xiàn)在是零),消費(fèi)者進(jìn)程返回到while的起始處,現(xiàn)在進(jìn)入if塊。
就在調(diào)用sleep之前,OS調(diào)度,決定將CPU時(shí)間片讓給生產(chǎn)者進(jìn)程,于是消費(fèi)者進(jìn)程在執(zhí)行sleep之前就被中斷了,生產(chǎn)者進(jìn)程開(kāi)始執(zhí)行。
生產(chǎn)者進(jìn)程生產(chǎn)出一項(xiàng)數(shù)據(jù)后將其放入緩沖區(qū),然后在itemCount上加 1;由于緩沖區(qū)在上一步加1之前為空,生產(chǎn)者嘗試喚醒消費(fèi)者。
遺憾的是,消費(fèi)者并沒(méi)有在休眠,喚醒指令不起作用。當(dāng)消費(fèi)者恢復(fù)執(zhí)行的時(shí)候,執(zhí)行 sleep,一覺(jué)不醒(出現(xiàn)這種情況的原因在于,消費(fèi)者只能被生產(chǎn)者在itemCount為1的情況下喚醒)。
生產(chǎn)者不停地循環(huán)執(zhí)行,直到緩沖區(qū)滿,隨后進(jìn)入休眠。
由于兩個(gè)進(jìn)程都進(jìn)入了永遠(yuǎn)的休眠,死鎖情況出現(xiàn)了。因此,該算法是不完善的。我們可以通過(guò)引入信號(hào)量(Semaphore)的方式來(lái)完善這個(gè)算法。信號(hào)量能夠?qū)崿F(xiàn)對(duì)某個(gè)特定資源的互斥訪問(wèn)。
// 該方法使用了兩個(gè)信號(hào)燈,fillCount和emptyCount; // fillCount用于記錄緩沖區(qū)中存在的數(shù)據(jù)項(xiàng)數(shù)量; // emptyCount用于記錄緩沖區(qū)中空閑空間數(shù)量; // 當(dāng)有新數(shù)據(jù)項(xiàng)被放入緩沖區(qū)時(shí),fillCount增加,emptyCount減少; // 當(dāng)有新數(shù)據(jù)項(xiàng)被取出緩沖區(qū)時(shí),fillCount減少,emptyCount增加; // 如果在生產(chǎn)者嘗試減少emptyCount的時(shí)候發(fā)現(xiàn)其值為零,那么生產(chǎn)者就進(jìn)入休眠。 // 等到有數(shù)據(jù)項(xiàng)被消耗,emptyCount增加的時(shí)候,生產(chǎn)者才被喚醒。 //?消費(fèi)者的行為類(lèi)似。 semaphore fillCount = 0; // 生產(chǎn)的項(xiàng)目 semaphore emptyCount = BUFFER_SIZE; // 剩余空間 procedure producer() { while (true) { item = produceItem(); down(emptyCount); putItemIntoBuffer(item); up(fillCount); } } procedure consumer() { while (true) { down(fillCount); item = removeItemFromBuffer(); up(emptyCount); consumeItem(item); } }b.分布式消息隊(duì)列服務(wù) 消息隊(duì)列中間件是分布式系統(tǒng)中重要的組件,主要解決應(yīng)用耦合、異步消息、流量削峰等問(wèn)題。消息(Message)是指在應(yīng)用之間傳送的數(shù)據(jù),消息可以非常簡(jiǎn)單,比如只包含文本字符串,也可以更復(fù)雜,可能包含嵌入對(duì)象。消息隊(duì)列(Message Queue)是一種應(yīng)用間的通信方式,消息發(fā)送后可以立即返回,有消息系統(tǒng)來(lái)確保信息的可靠傳遞,消息發(fā)布者只管把消息發(fā)布到MQ中而不管誰(shuí)來(lái)取,消息使用者只管從MQ中取消息而不管誰(shuí)發(fā)布的,這樣發(fā)布者和使用者都不用知道對(duì)方的存在。 如圖4,消息隊(duì)列一般由三部分組成:
Producer:消息生產(chǎn)者,負(fù)責(zé)產(chǎn)生和發(fā)送消息到 Broker。
Broker:消息處理中心。負(fù)責(zé)消息存儲(chǔ)、確認(rèn)、重試等,一般其中會(huì)包含多個(gè)Queue。
Consumer:消息消費(fèi)者,負(fù)責(zé)從 Broker 中獲取消息,并進(jìn)行相應(yīng)處理。
圖4 消息隊(duì)列模型 消息隊(duì)列具有如下特性:
異步性。將耗時(shí)的同步操作,通過(guò)發(fā)送消息的方式,進(jìn)行了異步化處理。減少了同步等待的時(shí)間。
松耦合。消息隊(duì)列減少了服務(wù)之間的耦合性,不同的服務(wù)可以通過(guò)消息隊(duì)列進(jìn)行通信,而不用關(guān)心彼此的實(shí)現(xiàn)細(xì)節(jié),只要定義好消息的格式就行。
分布式。通過(guò)對(duì)消費(fèi)者的橫向擴(kuò)展,降低了消息隊(duì)列阻塞的風(fēng)險(xiǎn),以及單個(gè)消費(fèi)者產(chǎn)生單點(diǎn)故障的可能性(當(dāng)然消息隊(duì)列本身也可以做成分布式集群)。
可靠性。消息隊(duì)列一般會(huì)把接收到的消息存儲(chǔ)到本地硬盤(pán)上(當(dāng)消息被處理完之后,存儲(chǔ)信息根據(jù)不同的消息隊(duì)列實(shí)現(xiàn),有可能將其刪除),這樣即使應(yīng)用掛掉或者消息隊(duì)列本身掛掉,消息也能夠重新加載。
互聯(lián)網(wǎng)場(chǎng)景使用較多的消息隊(duì)列有ActiveMQ、RabbitMQ、ZeroMQ、Kafka、MetaMQ、RocketMQ等。 c. 驅(qū)動(dòng)和設(shè)備通信 NIC(Network Interface Adapter,網(wǎng)絡(luò)接口卡)是典型的IO設(shè)備,網(wǎng)絡(luò)數(shù)據(jù)包的傳輸有發(fā)送Tx和接收Rx兩個(gè)方向。通過(guò)貢獻(xiàn)的Tx Queue和Rx Queue來(lái)交互數(shù)據(jù)傳輸。我們以網(wǎng)絡(luò)Tx的傳輸為例,介紹基于生產(chǎn)者消費(fèi)者模型的驅(qū)動(dòng)和設(shè)備數(shù)據(jù)交互。 如圖5,給出了網(wǎng)絡(luò)包處理Tx發(fā)送的基本原理示意圖(Rx接收跟Tx發(fā)送類(lèi)似,控制流程一致,數(shù)據(jù)方向相反)??梢钥吹?,在Tx的時(shí)候,驅(qū)動(dòng)是生產(chǎn)者,設(shè)備是消費(fèi)者,他們通過(guò)內(nèi)存中共享的環(huán)形隊(duì)列傳輸數(shù)據(jù)。一般在環(huán)形隊(duì)列中的是用于描述數(shù)據(jù)的描述符,通過(guò)指針指向?qū)嶋H的數(shù)據(jù)塊。當(dāng)上層應(yīng)用通過(guò)驅(qū)動(dòng)把數(shù)據(jù)寫(xiě)到環(huán)形隊(duì)列以后,驅(qū)動(dòng)會(huì)把環(huán)形隊(duì)列相關(guān)的狀態(tài)信息告知設(shè)備端。設(shè)備端接收到信息后DMA開(kāi)始工作,首先讀取環(huán)形隊(duì)列中的相應(yīng)描述符,然后通過(guò)描述符信息搬運(yùn)實(shí)際的數(shù)據(jù)塊到硬件內(nèi)部。搬運(yùn)完成后硬件通過(guò)中斷告知驅(qū)動(dòng),然后驅(qū)動(dòng)會(huì)釋放此塊緩沖。
圖5 網(wǎng)絡(luò)驅(qū)動(dòng)和設(shè)備通信示意圖
3 用戶態(tài)輪詢驅(qū)動(dòng):DPDK和SPDK
DPDK和SPDK是當(dāng)前主流的開(kāi)源高速接口框架,核心的技術(shù)是用戶態(tài)的輪詢驅(qū)動(dòng)。DPDK/SPDK支持兩個(gè)核心的設(shè)備類(lèi)型:DPDK聚焦高性能網(wǎng)絡(luò)處理,SPDK聚焦高性能存儲(chǔ)處理。 a. DPDK介紹
DPDK(Data Plane Development Kit,數(shù)據(jù)平面開(kāi)發(fā)套件)是在用戶態(tài)中運(yùn)行的一組軟件庫(kù)和驅(qū)動(dòng)程序,可加速在CPU架構(gòu)上運(yùn)行的數(shù)據(jù)包處理工作負(fù)載。DPDK由英特爾大約在2010年創(chuàng)建,現(xiàn)在作為Linux基金會(huì)下的一個(gè)開(kāi)源項(xiàng)目提供,在拓展通用CPU的應(yīng)用方面發(fā)揮了重要作用。
?
? |
? | ? |
? | |
(a) 基于Linux內(nèi)核的包處理 | (b) 基于DPDK的包處理 |
圖6 基于DPDK的包處理 如圖6(a),傳統(tǒng)Linux網(wǎng)絡(luò)驅(qū)動(dòng)存在如下一些問(wèn)題:
中斷開(kāi)銷(xiāo)大,大量數(shù)據(jù)傳輸會(huì)頻繁觸發(fā)中斷,中斷開(kāi)銷(xiāo)系統(tǒng)無(wú)法承受;
數(shù)據(jù)包從內(nèi)核緩沖區(qū)拷貝到用戶緩沖區(qū),帶來(lái)系統(tǒng)調(diào)用和數(shù)據(jù)包復(fù)制的開(kāi)銷(xiāo);
對(duì)于很多網(wǎng)絡(luò)功能來(lái)說(shuō),TCP/IP協(xié)議并非數(shù)據(jù)轉(zhuǎn)發(fā)必需;
操作系統(tǒng)調(diào)度帶來(lái)的緩存替換也會(huì)對(duì)性能產(chǎn)生負(fù)面影響。
如圖6(b),DPDK最核心的功能是提供了用戶態(tài)的輪詢模式驅(qū)動(dòng),為了加速網(wǎng)絡(luò)IO,DPDK允許傳入的網(wǎng)絡(luò)數(shù)據(jù)包直通到用戶空間而沒(méi)有內(nèi)存復(fù)制的開(kāi)銷(xiāo),不需要用戶空間和內(nèi)核空間切換時(shí)的上下文處理。DPDK可在高吞吐量和低延遲敏感的場(chǎng)景加速特定的網(wǎng)絡(luò)功能,如無(wú)線核心、無(wú)線訪問(wèn)、有線基礎(chǔ)設(shè)施、路由器、負(fù)載均衡器、防火墻、視頻流、VoIP等。DPDK所使用的優(yōu)化技術(shù)主要有:
用戶態(tài)驅(qū)動(dòng),減少內(nèi)核態(tài)用戶態(tài)切換開(kāi)銷(xiāo),減少緩沖區(qū)拷貝;
輪詢模式驅(qū)動(dòng)(PMD, Polling Mode Driver),不需要中斷,沒(méi)有中斷開(kāi)銷(xiāo),并且對(duì)隊(duì)列及數(shù)據(jù)及時(shí)處理,降低延遲;
固定處理器核,減少線程切換的開(kāi)銷(xiāo),減少緩存失效,同時(shí)要考慮NUMA特性,確保內(nèi)存和處理器核在同一個(gè)NUMA域中;
大頁(yè)機(jī)制,減少TLB未命中幾率;
非鎖定的同步,避免等待;
內(nèi)存對(duì)齊和緩存對(duì)齊,有利于內(nèi)存到緩存的加載效率;
DDIO機(jī)制,從IO設(shè)備把數(shù)據(jù)直接送到L3緩存,而不是送到內(nèi)存。
b. SPDK介紹 在數(shù)據(jù)中心中,固態(tài)存儲(chǔ)介質(zhì)正在逐漸替換機(jī)械HDD,NVMe在性能、功耗和機(jī)架密度方面具有明顯的優(yōu)勢(shì)。因?yàn)楣虘B(tài)存儲(chǔ)吞吐量提升,存儲(chǔ)軟件需要花費(fèi)更多的CPU資源;因?yàn)楣虘B(tài)存儲(chǔ)延遲性能的大幅提升,存儲(chǔ)軟件的處理延遲則開(kāi)始凸顯??偨Y(jié)來(lái)說(shuō),隨著存儲(chǔ)介質(zhì)性能的進(jìn)一步提升,存儲(chǔ)軟件棧的性能和效率越來(lái)越成為存儲(chǔ)系統(tǒng)的瓶頸。 如圖7,SPDK(Storage Performance Development Kit,存儲(chǔ)性能開(kāi)發(fā)套件)利用了很多DPDK的組件,在DPDK的基礎(chǔ)上,加入了存儲(chǔ)的相關(guān)組件。SPDK的核心技術(shù)依然是用戶態(tài)的PMD。SPDK已經(jīng)證明,使用一些處理器內(nèi)核和一些NVMe驅(qū)動(dòng)器進(jìn)行存儲(chǔ),而無(wú)需額外的卸載硬件,可以輕松實(shí)現(xiàn)每秒數(shù)百萬(wàn)個(gè)IO。
圖7 SPDK基于DPDK和一些新的組件 SPDK由許多組件組成,這些組件相互連接并共享用戶態(tài)和輪詢模式操作的通用功能。每個(gè)組件都是為了克服特定場(chǎng)景的性能瓶頸而開(kāi)發(fā)的,并且,每個(gè)組件也可以集成到非SPDK架構(gòu)中,從而使客戶可以利用SPDK的技術(shù)來(lái)加速自己的軟件應(yīng)用。從底層到上層,SPDK的組件包括:
用戶態(tài)PMD驅(qū)動(dòng):基于PCIe的NVMe驅(qū)動(dòng)、NVMeoF驅(qū)動(dòng),以及英特爾QuickData驅(qū)動(dòng)(QuickData為Intel志強(qiáng)處理器平臺(tái)的IO加速引擎)。
后端塊設(shè)備:Ceph RADOS塊設(shè)備(Ceph為開(kāi)源的分布式存儲(chǔ)系統(tǒng),RADOS為Ceph的分布式集群封裝),Blobstore塊設(shè)備(VM或數(shù)據(jù)庫(kù)交互的虛擬設(shè)備),Linux AIO(異步IO)。
存儲(chǔ)服務(wù):塊設(shè)備抽象層(bdev),Blobstore。
存儲(chǔ)協(xié)議:iSCSI Target端,NVMeoF Target端,vhost-scsi Target端,vhost-blk Target端。
編輯:黃飛
評(píng)論
查看更多