元件是在 Fuchsia 中執行軟體的基礎構成要素。每個元件都是可組合的沙箱模組,可透過功能與其他元件互動。這樣可以提升系統安全性,並在個別元件之間建立清楚的介面,方便更新或替換。
在 Fuchsia 中,「一切都是」元件 (幾乎)。先前的討論先前提過 Zircon 的討論區域,核心的介面區域刻意不大,而大部分的核心服務也都在使用者空間中實作。也就是說,在 Fuchsia 上執行的大多數軟體都是利用元件架構來實作,包括:
- 面向使用者的應用程式
- 裝置驅動程式
- 檔案系統
- 媒體轉碼器
- 網路堆疊
在核心以外,只有幾個未使用元件架構的低層級例外狀況,例如系統啟動載入程式和 userboot
程序。
元件管理工具
元件架構的核心是元件管理員。因此,負責協調所有元件執行個體的執行作業,提供其功能,並協調元件之間的連線。
元件可明確 (例如從網址) 啟動,或從特定能力的要求中隱含啟動。元件管理員會執行必要的解析度,以判斷是否要啟動新元件,或是將要求轉送至現有執行個體。為此,每個元件都必須宣告自身「提供」系統的任何功能,以及其「消耗」的任何功能。
元件管理員會剖析每個元件的「宣告」,以判斷如何執行元件及提供必要功能。元件通常會透過元件套件中的元件資訊清單檔案,向系統宣告。
以下是元件資訊清單的簡單範例,用於說明 ELF 執行檔和一些額外的指令引數:
program: {
runner: "elf",
binary: "bin/hello",
args: [ "Hello", "World!" ],
},
請注意執行階段宣告,向元件管理員說明這個元件需要 ELF 執行器。這是能力的範例!
元件功能
元件可透過「功能」capabilities取得較寬系統各部分的權限。每個元件都可宣告本身運作的功能,並提供給運作所需的其他元件 (或架構) 提供的系統和功能。
如您所見,runner
是宣告元件使用執行階段的能力範例。其他常見的能力類型範例包括存取檔案系統資源的 directory
,以及用於與其他元件通訊的 protocol
。
開發人員會使用元件資訊清單,宣告元件需要的能力類型。以下是要求兩項功能的元件資訊清單範例:具備 example-data
目錄的讀取權限,以及由 fuchsia.example.Foo
FIDL 通訊協定描述的服務。
use: [
{
directory: "example-data",
rights: [ "r*" ],
path: "/example/data",
},
{
protocol: "fuchsia.example.Foo",
},
]
元件管理員會使用能力宣告,在各個元件的命名空間中填入必要的目錄控點。在這個範例中,元件會在其命名空間接收 /example/data
和 /svc/fuchsia.example.Foo
。
元件整理
系統中的所有元件都會組成單一已取得 Root 權限的元件執行個體樹狀結構。這個樹狀結構可管理元件行為的幾個重要方面。
樹狀結構中的父項元件負責建立其他元件的執行個體做為子項,並提供必要功能。同時,子項元件可將功能向父項公開。建立子項元件的方式有以下兩種:
- 靜態:父項會在其元件宣告中宣告子項存在。
- 動態:父項使用
fuchsia.component.Realm
通訊協定,在執行階段將子項新增至元件集合。
任何父項元件及其所有子項會在樹狀結構中形成一個群組,稱為「運作範圍」。運作範圍可讓父項控管哪些功能傳入或傳出元件的子樹狀結構,藉此建立能力界線。元件會決定是否使用 expose
關鍵字匯出運作領域以外的功能:
expose: [
{
protocol: "fuchsia.example.Foo",
from: "self",
},
],
能力公開後,父項即可與相同領域中的其他元件共用該功能。方法是使用 offer
關鍵字:
offer: [
{
protocol: "fuchsia.example.Foo",
from: "self",
},
],
元件管理員這就是所謂的「功能轉送」。元件管理服務只能解析相同領域中公開及提供的功能。
運動:元件
在本練習中,您將探索元件執行個體樹狀結構,並藉由使用部分核心系統元件,詳細瞭解能力轉送實際運作情形。
啟動模擬器
如果您尚未有一個執行中的執行個體,請啟動模擬器:
ffx emu start --headless
啟動完成後,模擬器會輸出下列訊息並傳回:
Logging to "$HOME/.local/share/Fuchsia/ffx/emu/instances/fuchsia-emulator/emulator.log"
Waiting for Fuchsia to start (up to 60 seconds)........
Emulator is ready.
探索系統元件
開啟另一個終端機視窗,並使用 component list
指令轉儲系統元件樹狀結構:
ffx component list
畫面會顯示與下列 (截斷) 清單類似的輸出內容:
/
/bootstrap
/bootstrap/archivist
/bootstrap/base_resolver
/bootstrap/console
/bootstrap/console-launcher
/bootstrap/decompressor
/bootstrap/device_name_provider
/bootstrap/driver_manager
/bootstrap/fshost
/bootstrap/kernel_debug_broker
/bootstrap/miscsvc
/bootstrap/netsvc
/bootstrap/power_manager
/bootstrap/ptysvc
/bootstrap/pwrbtn-monitor
/bootstrap/shutdown_shim
/bootstrap/sysinfo
/bootstrap/virtual_console
/core
/core/activity
...
/core/detect
/core/font_provider
/core/log-stats
/core/remote-control
/core/sampler
/core/system-update-committer
/core/temperature-logger
/core/test_manager
/core/full-resolver
/startup
此清單代表元件執行個體樹狀結構,具有如 bootstrap
、core
和 startup
等機構元件,在根目錄底下形成子樹狀結構。
component show
指令會提供每個元件的詳細資料。
使用這個指令查看 http-client
的詳細資料 (提供 HTTP 要求服務的元件):
ffx component show http-client.cm
這個指令會輸出下列報表:
Moniker: /core/network/http-client
URL: #meta/http-client.cm
Type: CML static component
Component State: Resolved
Incoming Capabilities: config
fuchsia.logger.LogSink
fuchsia.net.name.Lookup
fuchsia.posix.socket.Provider
pkg
Exposed Capabilities: fuchsia.net.http.Loader
Merkle root: d9e73f5b061f2f227e596e2e0079ff3a095fc69e192cf85e0d7621826c76356c
Execution State: Running
Start reason: '/core/feedback' requested capability 'fuchsia.net.http.Loader'
Running since: ...
Job ID: 41268
Process ID: 41311
Outgoing Capabilities: fuchsia.net.http.Loader
請注意這裡列出的幾項詳細資料:
- 元件執行個體的專屬 ID (稱為「憑證」)。
- 載入這個元件的套件網址。
- 元件的執行狀態。
- 目前執行執行個體的工作/程序 ID。
- 為元件要求和公開的一組功能。
追溯能力路線
在先前的輸出內容中,有三個能力群組:
- 連入功能:元件使用
use
宣告的功能。這些引數會透過其「命名空間」提供給元件。 - 傳出功能:元件已發布至傳出目錄的功能。
- 公開功能:元件以
expose
宣告的功能。這些是元件的「公開服務」。
http-client
向父項 realm 公開的其中一項功能是 fuchsia.net.http.Loader。這可讓其他元件發出 HTTP 要求。
使用 component select
指令會決定與這項能力互動的元件數量:
ffx component capability fuchsia.net.http.Loader
這個指令會列出所有相符的元件:
Exposed:
/core/network/http-client
/core/network
Used:
/core/cobalt
/core/feedback
/core
這表示 cobalt
和 feedback
元件會使用此能力 (即列於「Incoming Capabilities」(傳入功能) 下方)。這些元件之間的共同祖係是 core
,會將這項能力轉送到必要的子項。