驅動程式和節點

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

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

節點拓撲圖:顯示從根節點到特定 SPI 裝置節點的階層,以及繫結至節點的驅動程式。

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

節點屬性

節點具有下列屬性:

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

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

節點功能

節點代表資源集合,而資源集合則代表 Fuchsia 系統中的硬體或虛擬裝置。當家長驅動程式庫建立新節點時,家長驅動程式庫會指定與該節點相關聯的功能。當子項驅動程式庫繫結至該節點時,驅動程式庫架構會將與節點相關聯的能力,路由至子項驅動程式庫的傳入命名空間。

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

節點拓撲

Fuchsia 的驅動程式管理員會維護節點拓撲,說明 Fuchsia 系統中節點 (代表裝置) 之間的父項/子項關係。從根節點開始,繫結至根節點的驅動程式庫會建立子節點,節點可擁有的子節點數量沒有限制。繫結至這些子節點的驅動程式通常會建立自己的子項。因此,這些節點會形成單一節點拓撲,以有向無環圖表示,說明在 Fuchsia 系統中探索到的所有硬體和虛擬裝置。

節點拓撲圖:顯示具有子項裝置的 USB 匯流排節點,並醒目顯示繫結至裝置節點的 USB 鍵盤驅動程式庫。

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

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

與元件拓撲的比較

與驅動程式庫架構類似,元件架構也有自己的拓撲,元件可在其中宣告子項。不過,節點拓撲和元件拓撲會分開。第一個原因是並非所有節點都可能繫結驅動程式。也就是說,這些未繫結的節點不會與元件拓撲中顯示的任何特定元件建立關聯。事實上,系統執行時,節點拓撲中的許多節點通常會保持未繫結狀態 (也就是與驅動程式不相符)。其次,在節點拓撲中,節點可能有多個父項節點 (請參閱「複合節點」),但元件拓撲不允許這種情況。

從元件架構的角度來看,驅動程式的拓撲似乎已扁平化。驅動程式庫架構會將驅動程式保留在三個元件的扁平集合中:啟動集合、套件集合和通用套件集合。在元件拓撲中,所有驅動程式庫元件都會顯示為父項元件 (即驅動程式管理器) 下的同層級元件。

元件拓撲圖:顯示驅動程式和驅動程式庫代管程序,這些項目會依集合歸類在 driver_manager.cm 下。

圖 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 方法時,系統會建立節點。擁有現有節點的驅動程式庫,或可存取節點物件的其他驅動程式庫,都可以在節點上觸發子節點建立作業。

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

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

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

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

移除節點

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

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

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

複合節點

當驅動程式庫想要將自己繫結至多個父項節點時,驅動程式管理器會建立複合節點。在本例中,驅動程式管理器會將複合節點新增至每個父項節點,做為子項節點。驅動程式管理器隨後會將驅動程式庫繫結至複合節點。

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

如下所示,攝影機可使用複合節點建立:

這張圖表顯示複合節點 (「camera」),以及繫結至驅動程式庫的兩個父項節點 (「gpio-enable」和「pci-device」)。

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

在上述範例中,系統在 Fuchsia 系統中探索到攝影機裝置。這部攝影機裝置具有可開啟攝影機的 GPIO 針腳,以及可將圖片資料從攝影機傳出的 PCI 裝置。驅動程式索引會將這個攝影機裝置與名為 camera-driver 的驅動程式庫相符。這個驅動程式庫具有複合繫結規則,表示它希望有兩個父節點:一個用於 GPIO 裝置,另一個用於 PCI 裝置。驅動程式管理器會建立名為 camera 的複合節點,並將該節點新增為 gpio-enable 節點和 pci-device 節點的子項。父項節點接著會將功能轉送至複合節點。最後,驅動程式管理器會將 camera-driver 驅動程式庫繫結至複合節點。

圖表:顯示攝影機控制器驅動程式庫程式的複雜繫結拓撲,其中有多個父項節點。

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