組織元件

系統中的所有元件都會組成根層級元件執行個體樹狀結構。樹狀結構中的父項元件負責將其他元件的例項宣告為子項,並提供功能。同時,子項元件可將功能向父項公開。這些元件執行個體和能力關係構成了「元件拓撲」

任何父項元件及其所有子項會在樹狀結構中形成一個群組,稱為「運作範圍」。運作範圍可讓父項控制哪些功能傳入或傳出元件的子樹狀結構,藉此建立能力界線。這個封裝允許在內部重組運作領域,不影響依附於其公開功能的外部元件。

這張圖表顯示元件執行個體如何組成樹狀結構,而父項元件會透過「能力轉送」決定每個子項可用的功能。

在上圖中,fuchsia.example.Foo 的通訊協定能力是透過元件執行個體樹狀結構轉送到用戶端。元件會使用 use 關鍵字宣告自身需要的功能:

{
    // Information about the program to run.
    program: {
        // Use the built-in ELF runner to run core binaries.
        runner: "elf",
        // The binary to run for this component.
        binary: "bin/client",
    },

    // Capabilities required by this component.
    use: [
        { protocol: "fuchsia.example.Foo" },
    ],
}

元件會使用元件資訊清單的 capabilities 區段,宣告本身實作的功能或「提供」。如此一來,元件架構就能知道能力及其供應器。請參閱以下 provider.cml 範例:

{
    // Information about the program to run.
    program: {
        // Use the built-in ELF runner to run core binaries.
        runner: "elf",
        // The binary to run for this component.
        binary: "bin/provider",
    },

    // Capabilities provided by this component.
    capabilities: [
        { protocol: "fuchsia.example.Foo" },
    ],
    // Capabilities routed through this component.
    expose: [
        {
            protocol: "fuchsia.example.Foo",
            from: "self",
        },
    ],
}

expose 關鍵字可透過其父項向其他領域提供能力,這可能也會包含此元件子項所提供的功能。在此情況下,能力的來源是 self,因為這個元件是供應器。

父項元件會控制領域中的功能轉送,進而建立從用戶端元件到供應器的明確路徑。請參閱以下 parent.cml 資訊清單範例:

{
    children: [
        {
            name: "provider",
            url: "fuchsia-pkg://fuchsia.com/foo-package#meta/provider.cm",
        },
        {
            name: "client",
            url: "fuchsia-pkg://fuchsia.com/foo-package#meta/client.cm",
        },
    ],
    offer: [
        {
            protocol: "fuchsia.example.Foo",
            from: "#provider",
            to: [ "#client" ],
        },
    ],
}

父項元件會宣告領域中的一組子項元件,並使用 offer 關鍵字將功能轉送至這些子元件。透過這種方式,父項會同時決定每個子項功能的範圍和來源。這也讓拓撲中的多個元件也能提供相同的能力,因為元件架構仰賴明確路徑來決定如何解決來自每個用戶端的要求。

功能類型

Fuchsia 元件支援多種不同類型的功能,目前,這個模組中的範例展示了兩種不同的能力類型:runnerprotocol。您可能已註意到,protocol 能力需要轉送路徑,但 runner 能力卻不需要。

部分功能會由父項「明確轉送」至元件,其他則會使用環境為「相同領域內」的所有元件提供。環境可讓架構佈建較不合理的功能,針對個別元件明確轉送功能。根據預設,元件會繼承其父項的環境。元件也可以為子項宣告新的環境。

下表列出可供元件使用的能力類型,以及元件是否必須明確從父項元件轉送,或由環境提供:

類型 說明 提供者
directory 其他元件提供的檔案系統目錄。 路線
event 元件管理服務產生的事件,例如元件啟動或能力要求。 路線
protocol 其他元件或架構提供的 FIDL 通訊協定。 路線
resolver 可解析元件資訊清單網址的元件。 環境
runner 用於執行特定元件的執行階段。 環境
service 執行常見工作的相關 FIDL 通訊協定的已命名群組。 路線
storage 每個元件專屬的獨立檔案系統目錄。 路線

識別元件

系統會透過網址識別元件。架構會利用元件解析器,將元件網址解析為元件宣告。解析器是本身能夠處理特定網址配置,以及擷取元件資訊清單、程式和資產的元件。

大多數的元件都會發布在 Fuchsia 套件中,因此元件網址是該套件中元件資訊清單的參照。請參閱以下範例:

fuchsia-pkg://fuchsia.com/foo-package#meta/foo-component.cm

元件執行個體是以公元路徑參照來識別,稱為「精靈」。元件的路徑名稱會以絕對或相對路徑表示元件執行個體樹狀結構中的位置。舉例來說,路徑名稱路徑 /core/system-updater 是指 core 領域中存在的 system-updater 執行個體。

元件生命週期

當您在元件拓撲中新增及移除元件執行個體時,即會建立及刪除元件執行個體。有兩種方法可以發生此情況:

  • 靜態:在元件資訊清單中,執行個體會宣告為樹狀結構中另一個元件的子項。只有在更新變更元件拓撲時,系統才會建立及刪除靜態元件。
  • 動態:在執行階段使用 fuchsia.component.Realm 通訊協定,在元件 collection 中新增或移除執行個體。動態元件會在系統關閉時刪除。

刪除元件後,架構會移除其持續狀態 (例如本機儲存空間)。

當另一個元件嘗試開啟元件的管道時,架構會啟動元件執行個體。連線至元件公開的能力時,會發生「隱含」情況。如果連線到已啟動的元件,系統就會重複使用執行中的執行個體。

元件可藉由退出程式自行停止 (依元件的 runner 定義),或者架構可能會在系統關閉的過程中停止元件。

顯示元件如何有「執行個體」和「執行」兩種不同狀態的圖表。這些狀態共同說明「元件生命週期」。

練習:整合元件

元件必須存在於使用中的元件拓撲中,才能叫用元件。在本練習中,您會將元件新增至 ffx-laboratory,這是在產品「核心領域」中用於開發的受限制集合。集合可讓在執行階段動態建立及刪除元件。

啟動模擬器

如果您尚未擁有執行中的執行個體,請透過網路支援啟動 FEMU:

ffx emu start workstation_eng.x64 --headless

發布套件

還記得 Fuchsia 裝置透過軟體推送功能,依需求解析套件存放區中的軟體套件。

使用 bazel run 指令建構並發布 echo 元件套件:

bazel run //fuchsia-codelab/echo:pkg.publish -- \
    --repo_name fuchsiasamples.com

這個指令會將套件發布至名為 fuchsiasamples.com 的存放區;如果該存放區不存在,請建立存放區,並向目標註冊該存放區。

新增至元件拓撲

使用下列指令建立新的 echo 元件執行個體:

ffx component create /core/ffx-laboratory:echo \
    fuchsia-pkg://fuchsiasamples.com/echo-example#meta/echo.cm

這個指令接受下列兩個參數:

  • /core/ffx-laboratory:echo:這是元件元件,代表元件執行個體元件拓撲中的路徑。
  • fuchsia-pkg://fuchsiasamples.com/echo-example#meta/echo.cm:這是元件網址,指出 Fuchsia 應如何從套件伺服器解析元件。

拓撲中現在有名為 echo 的新元件執行個體。使用下列指令顯示新執行個體的詳細資料:

ffx component show echo

您應該會看到下列輸出結果:

               Moniker: /core/ffx-laboratory:echo
                   URL: fuchsia-pkg://fuchsiasamples.com/echo-example#meta/echo.cm
                  Type: CML dynamic component
       Component State: Unresolved
       Execution State: Stopped

請注意,執行個體已建立,但元件網址尚未解析。當架構嘗試啟動執行個體時會發生解決方案。

啟動元件執行個體

使用下列指令啟動新的 echo 元件執行個體:

ffx component start /core/ffx-laboratory:echo

這個指令接受一個參數:

  • /core/ffx-laboratory:echo:這是元件元件,代表元件執行個體元件拓撲中的路徑。

這會導致元件執行個體啟動,並在記錄中顯示問候語,然後結束。開啟新的終端機視窗,並針對範例中的訊息篩選裝置記錄:

ffx log --filter echo

裝置記錄中應會顯示下列輸出內容:

[ffx-laboratory:echo][I] Hello, Alice, Bob, Spot!

探索執行個體

使用下列指令,再次顯示 echo 執行個體的詳細資料:

ffx component show echo

現在您應該會看到下列輸出結果:

               Moniker: /core/ffx-laboratory:echo
                   URL: fuchsia-pkg://fuchsiasamples.com/echo-example#meta/echo.cm
                  Type: CML dynamic component
       Component State: Resolved
 Incoming Capabilities: fuchsia.logger.LogSink
                        pkg
       Execution State: Stopped

元件狀態已變更為 Resolved,您可以查看更多元件功能的詳細資料。

元件不具備存取系統其他部分的環境功能。元件需要的每個能力都必須透過元件拓撲或由其環境提供,明確轉送給該元件。

echo 元件需要 fuchsia.logger.LogSink 能力寫入系統記錄。您只能成功查看記錄輸出,因為這項能力已從 core 領域「提供」ffx-laboratory 集合中的元件:

{
    collections: [
        {
            name: "ffx-laboratory",
        },
    ],
    offer: [
        {
            protocol: [ "fuchsia.logger.LogSink" ],
            from: "parent",
            to: "#ffx-laboratory",
        },
    ],
}

刪除執行個體

使用下列指令清除 echo 例項:

ffx component destroy /core/ffx-laboratory:echo