整理组件

系统中的所有组件都会组成一个已启用 root 权限的 组件实例树。树中的父组件负责 将其他组件的实例声明为其子组件并提供这些组件 功能。同时,子组件可以公开各种功能 返回给父级。这些组件实例和功能关系 设置组件拓扑

在树中,任何父级组件及其所有子级构成一个组,称为 realm。领域让父级可以控制哪些功能流入和流入 从其组件子树中移出,从而形成功能边界。这个 通过封装,我们可以在内部重新组织领域,而不会影响 依赖于其公开的功能。

显示组件实例如何组织为树和父级的示意图
决定每个子组件可用的功能,
“功能路由”

在上图中,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 关键字使相应功能可将功能从此组件提供给其他组件 这些领域,其中可能还包括此 子组件的子级。在本例中, capability 的来源为 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" ],
        },
    ],
}
<ph type="x-smartling-placeholder">

父组件声明 Realm 中的子组件集, 使用 offer 关键字向它们路由功能。这样,父级 确定每个子级功能的范围和来源。这也 拓扑中的多个组件提供相同的功能, 组件框架依靠显式路由来确定如何解析 从每个客户端发出的请求

功能类型

Fuchsia 组件支持许多不同类型的功能。到目前为止, 模块中,这些示例展示了两种不同的 capability 类型:runnerprotocol。您可能已经注意到,protocol 功能需要 路由路径,但 runner 功能不行。

有些功能由其父级显式路由到组件,而 使用 environments。环境使框架能够预配功能 这样毫无意义。默认情况下 组件会继承其父级的环境。组件还可以声明 为孩子打造全新的环境

<ph type="x-smartling-placeholder">

下表列出了组件可用的功能类型, 以及它们是必须从父组件显式路由,还是 由环境提供:

类型 说明 提供方
directory 其他组件提供的共享文件系统目录。 路由
event 由组件管理器生成的事件,例如组件启动或功能请求。 路由
protocol 其他组件或框架提供的 FIDL 协议。 路由
resolver 一种组件,能够解析指向组件清单的网址。 环境
runner 用于执行特定组件的运行时。 环境
service 执行常见任务的相关 FIDL 协议的命名组。 路由
storage 每个组件的独立文件系统目录都是唯一的。 路由

识别组件

组件通过网址进行标识。该框架将组件网址解析为 组件解析器进行组件声明。解析器 能够处理特定网址架构和 提取组件清单、程序和资源。

大多数组件都是在 Fuchsia 软件包中发布,因此组件网址是 对该软件包内的组件清单的引用。请参阅以下示例:

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

组件实例由拓扑路径引用(称为 名称。组件的名称表示其在组件中的位置。 是绝对路径还是相对路径。例如,名称路径 /core/system-updater 是指已存在的 system-updater 实例 在 core 领域中。

组件生命周期

在添加和移除组件实例时,组件实例会随之创建和销毁 在组件拓扑中可能通过以下两种方式之一发生:

  • 静态:在组件清单中将实例声明为子实例 另一个组件的创建。静态组件只会创建并 在更新更改组件拓扑时被销毁。
  • 动态:在组件 collection 中添加或移除实例 在运行时使用 fuchsia.component.Realm 协议。动态组件 它们会在系统关闭时被销毁

组件销毁后,框架将移除其持久状态 (例如本地存储)。

当另一个组件尝试执行下列操作时,框架将启动一个组件实例: 打开相应的频道当连接到 相应功能连接到组件 会重复使用正在运行的实例

<ph type="x-smartling-placeholder">

组件可通过退出程序(由 组件的 runner),或者框架可能会在出现以下情况时停止该组件: 系统关闭。

显示组件如何具有两种不同状态的示意图:实例和
执行。这些状态共同描述了“组件生命周期”。

练习:集成组件

要调用组件,组件必须存在于有效 组件拓扑在本练习中,您将向 ffx-laboratory - 用于开发的受限集合, 产品的核心领域。通过集合,组件可以动态地 是在运行时创建和销毁的

启动模拟器

如果您尚未运行实例,请启动模拟器:

  1. 启动新的模拟器实例:

    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.
    
  2. 启动软件包服务器,使模拟器能够加载软件包:

    fx serve
    

添加到组件拓扑

使用以下命令创建 echo-args 组件的新实例:

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

此命令接受两个参数:

  • /core/ffx-laboratory:echo-args:这是组件名称, 表示组件实例的组件拓扑内的路径。
  • fuchsia-pkg://fuchsia.com/echo-args#meta/echo_args.cm:这是 组件网址,指示 Fuchsia 应如何从 软件包服务器。

拓扑中现在存在一个名为 echo-args 的新组件实例。显示 新实例的详细信息:

ffx component show echo-args

您应该会看到以下输出内容:

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

请注意,实例已创建,但组件网址尚未 已解决。当框架尝试启动实例时,问题得到解决。

启动组件实例

使用以下命令启动新的 echo-args 组件实例:

ffx component start /core/ffx-laboratory:echo-args

此命令接受一个参数:

  • /core/ffx-laboratory:echo-args:这是组件名称, 表示组件实例的组件拓扑内的路径。

这会使组件实例启动,在日志中输出问候语。 然后退出。打开一个新的终端窗口,并过滤设备日志中的消息 从示例中进行选择:

ffx log --filter echo

您应该会在设备日志中看到以下输出:

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

探索实例

使用以下命令再次显示 echo-args 实例的详细信息:

ffx component show echo-args

您现在应看到以下输出:

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

组件状态已更改为 Resolved,您可以看到更多详情 组件功能

组件不具备访问系统其他部分的 Ambient 权能。 组件需要的每项功能都必须通过 组件拓扑或由其环境提供。

echo-args 组件需要 fuchsia.logger.LogSink 功能 写入系统日志。您已成功查看日志输出 因为此功能是提供给 ffx-laboratory 中的组件的 来自 core 大区的合集:

{
    collections: [
        {
            name: "ffx-laboratory",
        },
    ],
    offer: [
        {
            protocol: [ "fuchsia.logger.LogSink" ],
            from: "parent",
            to: "#ffx-laboratory",
        },
    ],
}
<ph type="x-smartling-placeholder">

销毁实例

使用以下命令清理 echo-args 实例:

ffx component destroy /core/ffx-laboratory:echo-args