Fuchisa Component介绍

在Fuchsia系统中,Component是最基本的执行单元,他们对外提供能力也消费其他组件的能力。

Component 和 Component Framework

在Fuchsia系统中,Component是运行于自己沙箱中的程序,他通过跨进程通信(FIDL)来与其他的Component的方式进行交互。
ComponentFramework是Fuchsia系统中面向组件的开发框架,组件框架负责运行几乎所有的软件。

组件化框架的优势

组件化框架关注与功能的分离,它帮助开发人员开发简单的组件,然后再使用这些简单的组件组合成负责的系统。
每个组件只负责实现单一的功能。例如网卡驱动组件只向外暴露收发网络帧的硬件服务接口。这些组件都遵循一套共同的协议,而无需关心这些组件是否来自于不同的开发商或者使用不同的开发语言开发。
软件组合具有的优点如下:

  • 可配置性:系统可以通过增加、删除、升级、替换不同的组件而改变行为。
  • 可扩展性:当增加一个组件时,系统的功能得到增长。
  • 可靠性:系统可以独立关闭或者重启故障组件。
  • 复用性:特定的组件可以通过组合来解决新问题。
  • 可测试性:组件可以进行单独测试和bug修改。
  • 一致性:组件使用相同的描述方式描述自己所能提供的能力。

Fuchsia使用组件化技术来构造整个具有组合能力的软件新系统,组件框架有利于新软件的发布和更新。

一切皆组件

组件无处不在,他们以相同的机制运行并无缝衔接,在Fuchsia系统中几乎一切程序都是以组件的形式存在的:

  • 命令行工具
  • 设备驱动
  • 用户应用
  • 文件系统
  • 多媒体编解码器
  • 网络协议栈
  • 测试程序
  • 网页

但是有几个例外:

  • bootloaders
  • 设备固件
  • kernels
  • 组件Manager自己的引导程序
  • 虚拟访客操作系统

组件的独立性

首先,组件是一个程序:

  • 它是软件的执行单元
  • 它使用一个唯一的URL进行标识,通过此URL可以查询并实例化组件
  • 组件可以使用任何的编程语言实现,只要由合适的组件runner(类似运行环境,后文有描述)存在
  • 它有一份声明用来描述它可以做什么和自己使用它的能力

然后,组件是一个独立的程序:

  • 每一个组件的实例都运行在自己的独立沙箱中。
  • 依据最小特权原则,组件被分配受限的权限以完成它的功能。
  • 组件不可以读取未被授权的其他组件
  • 组件的生命周期和状态独立于其他组件
  • 它主要通过IPC的方式与其他组件交互
  • 组件的错误和故障不会影响到整个系统的稳定。

其次,组件是一个可组合的程序:

  • 组件可以组合其他的组件从而形成复杂的组件
  • 组件可以通过静态或者动态的方式,使用其他组件的URL获得其他组件的实例作为当前组件的子组件。
  • 它可以使用功能路由将自己的能力授权给自己的子组件。

最终,组件是一个封闭的可以组合独立程序:

  • 组件有自己的封闭边界。
  • 组件可以在不影响调用者的情况下,改变自己的实现。
  • 组件以包含一切组件运行时所需的信息(包含共享库)的方式进行发布。

ComponentManager 及其启动

ComponentManager是Fuchsia组件框架的核心,它负责管理各组件的生命周期,对各组件进行授权管理和保持各组件的独立运行。
系统在启动的早期就启动组件管理器,然后组件管理器首先启动根组件,然后根组件像组件管理器发出请求,然后启动设备管理、文件系统、网络协议栈及其他必要的服务。
随着越来越多的组件启动,整个Fuchsia恢复生机,最终通过session framework启动用户交互,然后用户就可以控制系统了。

sequenceDiagram

participant BootProcess
participant ComponentManager
participant RootComponent
participant OtherComponent
participant SessionFramework

BootProcess->>ComponentManager: 启动
ComponentManager->>RootComponent: 启动
RootComponent->>ComponentManager: 请求启动核心Component
ComponentManager->>OtherComponent: 启动设备管理、文件系统等
BootProcess->>SessionFramework: 启动UI

组件实例

组件的实例是一个组件运行时的副本,不同的组件实例之间互不影响,状态等也互不干扰。推断一个组件可以由多个组件实例,且他们之间互无关系。

组件实例的生命周期

组件的实体有几个主要的生命周期事件:create、start、stop和destory。不同于进程,组件实例在不运行时依然存在,所以一个组件的实例可以被重复的启动和停止。

create

当一个组件被创建时,ComponentManager将为它分配一个唯一标识符,并将它存储在ComponentManager的数据结构中,并使其功能可供其他组件使用。
一旦创建,组件实例可被启动和销毁。

start

启动组件实例,组件中的代码将得到执行并且可以调用被赋予的其他组件中的能力。
每一个组件的运行都有其理由,ComponentManager只启动那些正的有事要做的组件,比方说有其他组件要调用该组件的能力。

stop

停止一个组件将停止该组件的程序运行,但是会保存组件运行到的状态,以便在下次运行时能够恢复组件的运行状态。ComponentManager可能由于以下的原因而停止一个组件:

  • 所有的客户端断开了连接
  • 其父组被停止
  • 当组件的包被更新
  • 当没有足够的资源运行该组件
  • 虽然有资源,但是其他的组件优先级更高
  • 组件被销毁
  • 系统关机

组件可以实现一个生命周期Handler用来接收生命周期事件,但是在资源耗尽,崩溃和系统关机的情况下组件将收不到事件的通知。
一旦停止,组件实例可以被重启或者销毁。

destory

销毁组件实例将释放他所占有的所有资源以及清楚其所有所状态。一旦被释放,组件实例将不能再被重启,再次启动同一组件,得到的将是不同的组件实例。

组件声明

一个组件的声明是给机器看的,它描述了该组件可以做什么和如何运行。它包含ComponentManager实例化组件实例和与其他组件组合时所需的元数据。
每一个组件都有一份组件声明,对于在包中分发的组件,组件的声明通常采用组件清单文件的方式(Component manifest file)。
组件也可以通过其他的方式发布,例如通过web application的方式发布,这是需要与之配套的解析器和运行器(runner),它们需要提供组件运行必须的声明。
例如,一个计算器组件声明可能包含如下信息:

  • 计算器的程序在包中所在的位置
  • 运行该组件的runner的名字
  • 保存计算器计算中间结果的持久化请求
  • 使用当前用户界面的请求
  • 请求公开允许其他组件使用进程间通信访问计算器累加器寄存器的功能。

组件URL

组件的URL指明了组件声明、组件的程序及资源所在的位置。可以使用不同的URL Scheme从不同的源检索组件,例如:

  • fuchsia-boot

该组件是从系统启动img中解析的,用于在包系统可用之前检索在早期引导期间对系统操作至关重要的组件。

1
eg: fuchsia-boot:///#meta/devcoordinator.cm
  • fuchsia-pkg

组件由Fuchsia包解析器解析。此方案用于以包的形式分发的组件,包可以按需下载并保持最新。

1
eg: fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cm
  • http/https

组件被web解析器解析为web应用程序。该方案用于将基于web的内容集成到组件框架中。

1
eg: https://fuchsia.dev

组件的拓扑结构

组件的拓扑结构是一个抽象的数据结构,用来描述组件实例之间的交互关系,它有三部分组成:

  • 组件实例树:描述组件实例以什么关系组合起来(他们之间的父子关系)
  • 能力路由图:描述组件实例如何获得对其他实例功能的访问权(他们之间的供销关系)
  • 共享资源树:描述隔离在各自沙箱中的各组件对共享资源使用方式(他们的隔离关系)

组件拓扑结构对组件的生命周期和功能的使用有很大的影响。

层次结构

通过层次结构,一些简单的组件可以组合在一起形成一个复杂的组件。在层次结构中父组件创建其他组件的实例作为其子组件,父组件为其子组件赋予访问父组件能力的权限,同时通过功能路由的方式访问子组件的能力。子组件可以通过如下两种方式被创建:

  • 静态

父组件在自己的声明中声明子组件,子组件在父组件更新声明删除子组件后将会自动销毁。

  • 动态

父组件使用领域(ComponentManager组件树的一个子树)服务创建子组件并加载到父组件定义的组件集合中,对子组件的管理使用同样的方法。

子组件永远依赖父组件;他们不能被重新分配,也不能比父组件长寿。当父组件被销毁时,所有的子组件也会被销毁。组件之间的拓扑关系代表了组件之间的父子关系,这种关系以组件实例树的形式存在。

封装

子组件的能力不能直接对外提供,必须经由其父组件,这些功能是被封装的。这个特性类似于面向对象编程中的组合。

领域

领域是由层次结构组成的组件实例的子树。每个领域都由一个组件实例根,并包含该实例的所有子实例及其子实例。领域是组件拓扑结构中重要的封装边界。每个领域的根都有某些特权来影响组件的行为,例如:

  • 声明能力如何在领域内 流入、流出和在流动
  • 绑定到子组件以访问其服务。
  • 创建和销毁子组件。

能力路由

组件可以通过功能路由访问其他组件公开的功能。

Compartments

Compartments是组件实例运行的隔离边界。它是维护组件的机密性、完整性和可用性的重要机制。运行于不同物理硬件、不同job、不同runner的组件之间是互相隔离的。上述的三层隔离是互相嵌套的。runner 运行于 job(类似于进程)中,而job运行于物理硬件上。kernel负责对job的调度。

综上,组件是fuchsia运行程序的一个基本单位,在fuchsia分发pacakge时,一个包可以携带多个组件,组件有点类似于android 四大组件的感觉,但是感觉要更加独立,且还有自己的层级结构。运行时,组件的依赖需要依赖runner,在fuchsia的框架中,这个runner是可扩展的,这将极大的丰富fuchsia的生态。runner有点像解析器或者虚拟机的感觉。runner运行于job,job则类似于进程的概念,由kernel进行调度。
Fuchsia出现的新概念太多,需要类比学习帮助理解,多有不当之处,欢迎大家讨论。

robot wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
坚持原创技术分享,您的支持将鼓励我继续创作!