驅動程式和節點

在 Fuchsia 中,每個驅動程式庫都會繫結至一個節點。節點是驅動程式架構的主要構成要素。節點可視為硬體或虛擬裝置,也可以視為硬體裝置的一部分。舉例來說,GPIO 節點可以代表連接到 GPIO 控制器的一個 GPIO 接腳,而 RAM 磁碟節點可以代表虛擬磁碟,而不是實體硬體裝置。

驅動程式在繫結至節點時會建立子節點。因此,節點會形成有向非循環圖,代表 Fuuchsia 系統中的所有已知硬體和虛擬裝置。

alt_text

圖 1. 一個節點拓撲,綠色圓圈代表裝置的節點,藍色方塊是驅動程式。

節點屬性

節點具有以下屬性:

  • 節點屬性:鍵/值組合,描述哪些驅動程式庫可「繫結」bind至節點。鍵可以是整數或字串類型。這個值可以是整數、字串、布林值或列舉類型。
  • 功能:當驅動程式繫結至節點時,提供給驅動程式庫的 FIDL 功能。這些項目可以是處理中和程序外的功能。
  • 符號:鍵/值組合,其中鍵為字串,而值是虛擬位址。驅動程式會使用這些符號來將指標指向子項驅動程式庫,進行程序內通訊。只有當驅動程式與父項位於相同的驅動程式主機中時,才會提供給驅動程式。否則,驅動程式庫會使用 FIDL 呼叫進行通訊。

建立子節點的驅動程式會將節點屬性、功能和符號指派給新節點。

節點功能

節點代表一系列資源,反過來代表 Fuchsia 系統中的硬體或虛擬裝置。父項驅動程式庫建立新節點時,父項驅動程式庫會指定與該節點相關聯的功能。當子項驅動程式庫繫結至該節點時,驅動程式庫架構會將與節點相關聯的功能轉送至子項驅動程式庫的傳入命名空間。

不過,驅動程式傳入的命名空間中的所有功能並非來自父項驅動程式庫。某些功能可能是來自系統的非驅動程式庫元件。

節點拓撲

Fuchsia 的驅動程式管理員維持一個節點拓撲,說明 Fuchsia 系統中節點 (代表裝置) 的父項與子項關係。從根節點開始,繫結至根節點的驅動程式庫會建立子節點,每個節點的子項數量沒有限制。繫結這些子節點的驅動程式通常會建立自己的子項。因此,這些節點會形成單一節點拓撲,以有向非循環圖表示,其中描述在 Fuchsia 系統中發現的所有硬體和虛擬裝置。

alt_text

圖 2:USB 匯流排拓撲範例。

在上述範例中,USB 匯流排驅動程式 (usb-bus-driver) 會繫結至代表 USB 匯流排的節點 (usb-bus)。然後,驅動程式會針對系統中發現的每部新 USB 裝置建立子節點。視節點的屬性而定,每個 USB 裝置節點都可以繫結特定的 USB 驅動程式庫。舉例來說,USB 鍵盤驅動程式庫 (usb-keyboard-driver) 會繫結至其中一個 USB 裝置節點。我們可以猜出 usb-device-2 節點可能是透過 USB 連接埠連線至系統的鍵盤裝置。

與元件拓撲比較

與驅動程式庫架構類似,元件架構有自己的「拓撲」,其中元件可宣告子項。不過,節點拓撲和元件拓撲會分開保存。第一個原因是,並非所有節點都有繫結驅動程式。也就是說,這些未繫結的節點與元件拓撲中顯示的任何特定元件沒有關聯。事實上,在系統運作時,節點拓撲中通常會有許多節點處於不受限制 (也就是說,這些節點與驅動程式不相符)。其次,在節點拓撲中,一個節點可以有多個父項節點 (請參閱複合節點),這不適用於元件拓撲。

從元件架構的角度來看,驅動程式的拓撲似乎經過簡化。驅動程式庫架構會將驅動程式區分為三個元件集合:啟動收集、套件集合和宇宙套件集合。在元件拓撲中,所有驅動程式庫元件都似乎在其父項元件 (也就是驅動程式管理器) 底下,是彼此的同層級。

alt_text

圖 3:顯示三個集合中的驅動程式庫元件的元件拓撲

不過,不同於元件拓撲中的其他元件,驅動程式庫架構會負責設定驅動程式庫元件的「精靈」。驅動程式架構會根據驅動程式在節點拓撲中的位置 (而非元件拓撲) 為驅動程式庫元件的路徑名稱命名。舉例來說,PCI 驅動程式的元件路徑名稱可能看起來類似 /bootstrap/boot-drivers:root.sys.platform.pci.00_14_0。此元件路徑名稱暗示 PCI 驅動程式庫的下列節點拓撲:root -> sys -> platform -> pci -> 00_14_0。元件路徑名稱顯示此 PCI 驅動程式庫元件在元件拓撲中只有 2 層,而繫結至 PCI 驅動程式庫的節點 (00_14_0) 是位於節點拓撲中的第 5 層。

節點生命週期

Fuchsia 系統中的驅動程式生命週期與繫結的節點生命週期相連結。

驅動程式可以在所控管的 Node 物件中執行下列生命週期動作:

建立節點

在現有節點呼叫 AddChild FIDL 方法時,系統會建立節點。擁有現有節點的驅動程式庫或其他可存取節點物件的驅動程式庫,都能在節點上觸發子節點建立作業。

當驅動程式庫建立子節點時,驅動程式庫可執行下列動作:

  • 為子節點提供屬性,以決定哪些驅動程式可繫結至節點。
  • 為子節點提供capabilities,以供之後繫結至節點的驅動程式庫使用。
  • 保留子節點的 NodeController 物件,這個物件可讓父項驅動程式庫停止子節點。

當驅動程式庫建立子節點時,驅動程式庫可以選擇擁有該節點。為擁有子節點,驅動程式庫會在 AddChild 呼叫中新增額外引數。如果驅動程式庫要求擁有子節點,驅動程式庫架構不會將新的驅動程式庫繫結至節點。然而,如果子節點不屬於驅動程式庫所擁有,驅動程式庫架構會嘗試尋找可繫結至新節點的其他驅動程式庫。

當驅動程式庫建立子節點時,驅動程式庫也能保留子項節點的 NodeController 物件。驅動程式可隨時使用這個物件 (透過呼叫 Remove) 來停止子節點,導致停止繫結至節點的驅動程式庫。當子節點繫結至驅動程式庫時,驅動程式庫會透過這個物件接收 OnBind FIDL 事件。

移除節點

發生下列任一事件時,系統就會移除節點:

  • 繫結至節點的驅動程式會捨棄其 Node 物件。
  • 節點 (例如父項節點) 會在目標節點的 NodeController 物件上呼叫 Remove 方法。
  • 元件架構會關閉驅動程式庫元件,因此會移除繫結至節點的驅動程式庫。

在節點拓撲中,節點會先從底部移除。如果節點已繫結至驅動程式庫,您必須先停止驅動程式庫,才能移除節點。如果要移除的節點位於節點拓撲中間,則驅動程式庫架構可確保所有子項驅動程式都會停止運作,且所有子節點都會在移除目標節點前移除。

複合節點

當驅動程式庫希望自行繫結至多個父項節點時,驅動程式管理器會建立複合節點。在這種情況下,驅動程式管理器會將複合節點新增至每個父項節點做為子項節點。接著,驅動程式管理器會將驅動程式庫繫結至複合節點。

複合節點具有複合式繫結規則,可讓驅動程式庫為每個父項節點指定不同的繫結規則組合。系統會從每個父項節點轉送複合節點的功能,讓驅動程式庫存取父項節點的合併功能。不過,繫結屬性不會從父項節點轉送至複合式節點。建立複合節點時,驅動程式庫架構會建立複合節點,藉此回應驅動程式庫與多個父項節點的繫結,因此已知將繫結至節點的驅動程式庫。

您可以使用複合節點製作相機,如下所示:

alt_text

圖 4. 複合節點的表示法。

在上述範例中,在 Fuchsia 系統中發現相機裝置。此相機裝置具有會開啟相機的 GPIO 接腳,以及可將相機從相機中轉移圖片的 PCI 裝置。驅動程式索引會將這部攝影機裝置與名為 camera-driver 的驅動程式庫進行比對。這個驅動程式庫有複合式繫結規則,表示想要有兩個父項節點:一個用於 GPIO 裝置,另一個適用於 PCI 裝置。驅動程式管理器會建立名為 camera 的複合節點,並將節點新增為 gpio-enable 節點和 pci-device 節點的子項。接著,父項節點會將其功能轉送至複合式節點。最後,驅動程式管理器會將 camera-driver 驅動程式庫繫結至複合節點。

alt_text

圖 5:實際範例顯示相機控制器驅動程式庫的複雜繫結拓撲