Banjo-to-FIDL 遷移的常見問題

開始進行 Banjo 遷移至 FIDL 作業前,請先參閱下列常見問題,找出可能適用於驅動程式的特殊情況或極端案例。

Banjo 和 FIDL 有何不同?

Banjo 是「轉譯器」(類似於 FIDL 中的 fidlc)。它會將介面定義語言 (IDL) 轉換為特定目標語言的檔案。FIDL 是 Fuchsia 的處理序間通訊 (IPC) 系統。

驅動程式庫執行階段的新功能

驅動程式可能會與驅動程式庫架構、其他驅動程式和非驅動程式庫元件等實體通訊。在同一個驅動程式代管程序中,通訊可以使用由驅動程式庫執行階段傳輸基本類型 (即競技場、管道和調度器) 支援的 FIDL 繫結進行。這個新版 FIDL 稱為「驅動程式執行階段 FIDL」。驅動程式執行階段 FIDL 可讓驅動程式發揮新驅動程式庫執行階段的優勢,包括穩定的 ABI、執行緒安全、效能、驅動程式庫程式作者人體工學、安全性和韌性。(詳情請參閱這份 RFC)。

我是否需要遷移 DFv1 驅動程式庫,才能使用驅動程式庫執行階段?

從 Banjo 遷移 DFv1 驅動程式庫至 FIDL 時,只有在驅動程式庫程式與位於相同驅動程式代管程序的其他驅動程式通訊時,才需要遷移驅動程式庫程式執行階段。(請參閱下方的「如何判斷驅動程式是否會與同一程序中的其他驅動程式通訊?」)。

將驅動程式庫遷移至新版驅動程式庫執行階段的一大優點是,這會改變驅動程式庫與共置驅動程式的通訊方式,也就是使用驅動程式庫執行階段 FIDL。不過,如要開始遷移驅動程式庫以使用驅動程式庫執行階段,如果驅動程式使用 Banjo 或已使用 FIDL,但 FIDL 是以原始傳輸 (Zircon 基本類型) 為基礎,您必須先進行變更,確保驅動程式庫中的所有通訊都使用 FIDL。

好消息是,驅動程式庫執行階段 FIDL 的語法與 FIDL C++ 連線繫結類似。唯一的差別在於函式呼叫中會有一些額外參數。此外,部分類別或基本體的命名空間為 fdf,而非原始命名空間 (例如 fdf::WireServer),但 FIDL 連結類型仍用於資料交易 (例如 fidl::VectorView)。

如何判斷我的驅動程式庫是否與位於相同程序的其他驅動程式通訊?

如要瞭解驅動程式是否與位於同一程序中的其他驅動程式通訊 (如果是,您需要遷移驅動程式庫以使用驅動程式庫執行階段),請檢查驅動程式庫的元件資訊清單檔案 (.cml),並尋找 colocate 欄位,例如:

program: {
  runner: "driver",
  compat: "driver/wlansoftmac.so",
  bind: "meta/bind/wlansoftmac.bindbc",
  colocate: "true",
  default_dispatcher_opts: [ "allow_sync_calls" ],
},
use: [
  { service: "fuchsia.wlan.softmac.Service" },
],

(來源:wlansoftmac.cml)

如果 colocate 欄位為 true,這個驅動程式庫會與位於同一程序的其他驅動程式通訊。

如要查看哪些驅動程式位於同一位置,可以執行 ffx driver list-hosts 指令,例如:

$ ffx driver list-hosts
...
Driver Host: 11040
  fuchsia-boot:///#meta/virtio_netdevice.cm
  fuchsia-boot:///network-device#meta/network-device.cm

Driver Host: 11177
  fuchsia-boot:///#meta/virtio_input.cm
  fuchsia-boot:///hid#meta/hid.cm
  fuchsia-boot:///hid-input-report#meta/hid-input-report.cm

Driver Host: 11352
  fuchsia-boot:///#meta/ahci.cm

...

位於同一位置的驅動程式會共用相同的驅動程式代管程序。在本範例中,virtio_netdevice.cmnetwork-device.cm 驅動程式位於同一位置。

何時需要使用調度器?

不建議在驅動程式中建立執行緒。因此,驅動程式必須改用調度器。調度器是虛擬執行緒,會排定在驅動程式庫執行階段執行緒集區中執行。FIDL 檔案會產生用戶端和伺服器範本與資料類型,而這些用戶端和伺服器端之間是管道,兩端的調度器會從管道擷取資料。

分派器專用於驅動程式庫執行階段,與 DFv1 和 DFv2 無關。雖然分派器可用於其他用途 (例如等待核心的中斷),但主要用於 FIDL 通訊。

從 Banjo 遷移至 FIDL 時,新執行緒模型會造成哪些問題?

FIDL 呼叫並非以單一執行緒為基礎,且設計上為非同步 (雖然您可以將 .sync() 新增至 FIDL 呼叫或使用 fdf::WireSyncClient,使其同步)。一般不建議驅動程式進行同步呼叫,因為這可能會阻礙其他工作執行。(不過,如有必要,驅動程式庫可以使用 FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS 選項建立調度器,但這只支援同步調度器)。

從 Banjo 遷移至 FIDL 時,您可能會遇到的第一個問題是,與 FIDL 不同,Banjo 會將 IDL (介面定義語言) 轉換為由函式指標或資料型別組成的結構。因此,從本質上來說,使用 Banjo 橋接驅動程式,就是使用同步函式呼叫橋接驅動程式。

由於 Banjo 和 FIDL 的執行緒模型有所不同,因此在遷移時,您需要決定要使用哪種 FIDL 呼叫 (即同步或非同步)。如果原始程式碼是圍繞 Banjo 的同步性質設計,難以解除以全非同步方式運作,建議您先考慮使用 FIDL 的同步版本 (但這可能會導致暫時的效能下降)。之後,您可以重新檢視這些呼叫,並將其最佳化為使用非同步呼叫。

從 Banjo 遷移至 FIDL 後,我需要在驅動程式庫程式的單元測試中進行哪些變更?

如果驅動程式有以 Banjo API 為基礎的單元測試,您需要在測試類別中建立模擬 FIDL 用戶端 (或伺服器,視您要測試伺服器或用戶端而定)。詳情請參閱「Update the DFv1 驅動程式庫's unit tests to use FIDL」。