VMO 註冊模式

摘要

在應用程式和周邊硬體之間傳輸大量資料時,請務必盡可能減少資料的複製次數。舉例來說,假設應用程式想要從元件永久性儲存空間讀取檔案。為此,應用程式會向檔案系統提出讀取檔案的要求,而檔案系統可能需要向區塊裝置傳送要求。視區塊分割拓樸結構而定,要求可能會經過多個驅動程式層級,最後才會命中可執行讀取作業的驅動程式庫。

上述方法可能會導致透過 Zircon 管道,在應用程式和硬體之間的每個層級傳送 FIDL 訊息,導致資料出現許多副本。這麼做效率不高,因此我們不會這麼做。我們遵循業界成熟的模式,將訊息分為兩個層級:控制層和資料層。透過控制層傳送的訊息體積較小,傳送費用也較低,但資料層中的訊息包含大量資料,因此複製費用較高。透過控制層傳送的郵件通常會使用以 Zircon 管道為基礎建構的 FIDL 通訊協定。資料層中的訊息會透過共用記憶體原語,也就是 Zircon VMOs 傳送。

考量這一點,初步實作可能會選擇為每筆交易建立新的 VMO,這些交易會透過控制層傳送,直到到達發出 DMA 的驅動程式庫為止,藉此達成預期目標,即在將資料放入 VMO 的應用程式和最終驅動程式庫之間,不產生任何副本。不過,這可能無法達到理想的效能,原因如下:

  • 為了發出 DMA 要求,必須先將記憶體釘住,這需要呼叫核心,並視需要在 IOMMU 中設定頁面對應。
  • 如果最終驅動程式庫需要將要求複製到特殊緩衝區 (並非所有硬體都支援 DMA),則必須將 VMO 對應至其程序,或呼叫至核心,才能複製記憶體。

由於這兩種方法都成本高昂,因此我們需要更有效的方法:使用預先註冊的 VMOs。這項功能運作方式是讓應用程式傳送一次性控制訊息,以便將 VMO 註冊至堆疊中的最終驅動程式庫。此訊息的回應會傳回一個 ID,日後可用於參照 VMO。控制訊息應只參照這個 ID,而非附加 VMO 句柄。註冊後,堆疊中的最終驅動程式庫可以執行一次成本較高的固定或對應作業,並將結果快取。

VMO ID 相關注意事項

為確保不會遭受混淆代理攻擊,我們必須維持 VMO ID 的相同不變量,就像核心處理程式處理句柄一樣。為此,VMO ID 必須是每個層級中客戶專屬的 ID,且每個層級都必須驗證 ID 是否有效。具體來說,使用 koid 做為 ID 仍需要伺服器檢查用戶端是否已註冊該 koid 的 VMO。

為降低往返次數,您可以讓用戶端將 VMO ID 命名為註冊 API 的一部分,讓單次 VMO 用途更有效率。或者,您也可以在通訊協定中指出,系統一律會使用 VMO 的 koid 做為 ID。

Zircon FIFO

為了進一步提升效能,部分通訊協定也可能會選擇在控制層使用 FIFO。FIFO 可降低複雜度,因此可降低額外負擔。其中一個限制是無法轉移句柄。因此,如要使用 FIFO,就必須使用 VMO 註冊模式。(請注意,您仍必須使用管道才能註冊)。

媒體庫

這個模式可能會為驅動程式庫增加許多複雜性,因為驅動程式會維護 VMO 與 ID 之間的對應關係。我們已建立程式庫來協助實作,並位於 //src/lib/vmo_store 下。如需使用範例,請參閱 //src/connectivity/network/drivers/network-device/device

模式的缺點

在吞吐量偏低的情況下,這種模式不必要地複雜,因此應避免使用。

VMO 註冊會導致一次性作業變成 2 次往返作業。如果一次性用途很常見,FIDL 通訊協定應確保除了預先註冊的 VMOs 外,也能使用一次性用途的 VMOs。您也可以在註冊期間允許用戶端提供 VMO 的 ID,藉此緩解這個問題。

預先註冊的 VMOs 可能會導致「記憶體外洩」情況,也就是用戶端會持續註冊 VMOs,但忘記取消註冊。此外,如果伺服器未妥善管理用戶端,可能會忘記清除屬於用戶端的已註冊 VMOs,而該用戶端可能已與伺服器中斷連線。

預先註冊 VMOs 的驅動程式庫程式會將 VMOs 固定,導致支援 VMO 的頁面無法再分頁。

駕駛員專屬注意事項

由於部分驅動程式會駐留在相同的驅動程式代管程序程序中,且我們採用迷你驅動程式庫模式,將常用邏輯提升至「核心」驅動程式庫,因此在核心驅動程式中執行 VMO 註冊作業,而非在裝置專屬驅動程式庫中執行,似乎是顯而易見的做法。不過,基於下列原因,這並非明智之舉:

  • 核心驅動程式需要知道是否要由裝置專屬驅動程式庫執行固定或對應作業。
  • 固定需要存取平台匯流排或 PCI 驅動程式提供的匯流排交易啟動程式 (BTI) 句柄。將 BTI 句柄傳遞至驅動程式庫堆疊是反模式。
  • 在需要對應的情況下,這表示原始緩衝區會透過 Fidl 傳遞。這是反模式,因為在這種情況下,傳送資料時無法避免複製資料。
  • 無論是哪種情況,如果作業為非同步作業 (大多數都是),核心驅動程式就必須負責確保在使用 VMO 時,不會將其解綁/取消對應。在未經過充分測試的關機和暫停等情況下,這會造成特別嚴重的問題。