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

開始進行 Banjo 至 Fidl 的遷移作業前,請先參閱下列常見問題,瞭解可能適用於驅動程式的特殊情況或邊緣情況。

Banjo 和 FIDL 有何不同?

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

驅動程式庫執行階段有哪些新功能?

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

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

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

將驅動程式庫遷移至使用新的驅動程式庫執行階段,其中一個主要優點是,它會改變驅動程式庫與共置驅動程式通訊的方式,這項操作是透過使用驅動程式庫執行階段 FIDL 完成。不過,在開始遷移驅動程式庫以便使用驅動程式庫執行階段之前,如果驅動程式使用 Banjo 或已使用 FIDL,但以原始傳輸 (Zircon 原始碼) 為基礎,您必須先進行變更,讓驅動程式庫中的所有通訊都使用 FIDL。

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

如何得知我的驅動程式庫是否與在同一程序中執行的其他驅動程式通訊?

如要瞭解驅動程式是否與同一程序中同時位於同一位置的其他驅動程式通訊 (在這種情況下,您需要遷移驅動程式庫以使用驅動程式庫執行階段),請檢查驅動程式庫的元件資訊清單檔案 (.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 通訊,但也可以用於其他用途,例如等待來自核心的中斷。

將 DFv1 驅動程式庫從 Banjo 遷移至 FIDL 時,新執行緒模型有哪些問題?

FIDL 呼叫並非以單一執行緒為基礎,且設計上為非同步 (不過,您可以透過在 FIDL 呼叫中加入 .sync() 或使用 fdf::WireSyncClient 將其設為同步)。一般來說,不建議驅動程式進行同步呼叫,因為這可能會阻止其他工作執行。(不過,如果需要,驅動程式庫可以使用 FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS 選項建立調度器,但這項選項僅支援同步調度器)。

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

考量 Banjo 和 FIDL 之間的執行緒模型差異,您需要決定在遷移時要使用哪種 FIDL 呼叫 (即同步或非同步)。如果原始程式碼是根據 Banjo 的同步性質設計,且難以解開並使其全部非同步,建議您一開始使用 FIDL 的同步版本 (但這可能會導致效能暫時降低)。之後,您可以重新查看這些呼叫,並將其最佳化為使用非同步呼叫。

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

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