Fuchsia 系统接口

概览

Fuchsia 系统接口是 Fuchsia 操作系统提供给其运行的软件的二进制接口。该接口的基础是 vDSO,可以提供对系统调用的访问权限。不允许程序直接发出系统调用(例如通过陷入内核中)。而是使用 vDSO 与内核进行交互。

大部分系统接口通过进程间通信协议提供,通常使用 FIDL 定义。这些协议通过各种内核基元(包括通道和套接字)使用。

fuchsia.io FIDL 库为文件和目录操作提供了协议。Fuchsia 使用 fuchsia.io 协议为组件提供一个命名空间,组件可以通过该命名空间访问系统服务和资源。这些命名空间中的名称遵循某些惯例,属于系统 ABI 的一部分。如需了解详情,请参阅命名空间

软件包本身还在目录结构和文件格式方面为系统提供接口。系统会使用此信息来初始化执行这些软件包中存储的组件的进程。

术语

系统的应用编程接口 (API) 是系统的源代码级接口。您通常需要直接编写使用此接口的软件。对系统 API 的更改可能需要您根据 API 的更改更新源代码。

系统的应用二进制接口 (ABI) 是系统的二进制级接口。通常,您不能直接编写使用系统 ABI 的软件,而是要针对系统 API 编写软件。编译软件时,编译器创建的二进制工件会通过 ABI 与系统连接。对系统 ABI 的更改可能需要您重新编译源代码,以考虑 ABI 的更改。

ABI 接口

本部分介绍了 Fuchsia 组件的各种 ABI Surface。

vDSO

vDSO 是一个提供对内核的访问权限的虚拟共享库。具体而言,vDSO 是一个名为 libzircon.so 的 ELF 共享库,它按照 C 调用惯例导出多个符号。这些符号的可信来源是 //zircon/vdso。如需了解其语义,请参阅相关文档

FIDL 协议

大多数系统接口都是使用 Fuchsia 接口定义语言 (FIDL) 定义的。FIDL 编译器会针对各种目标语言生成特定于语言的 API 和运行时库(称为 FIDL 绑定)。这些绑定提供了一个惯用接口,用于通过 Zircon 通道(和其他基元)收发进程间通信消息。

电汇格式

FIDL 协议定义本身和由编译器生成的特定语言的绑定是系统 API 的一部分,而不是系统 ABI 的一部分。相反,序列化消息的格式(称为有线格式)包含 ABI。FIDL 传输格式由规范定义。

用户信号

除了发送的消息外,有些 FIDL 协议还会利用底层内核对象上的用户信号。目前,这些信号未在 FIDL 中声明。通常,任何关联用户信号的语义都会逐条记录在 FIDL 定义的注释中。

命名空间惯例

命名空间和传出目录中的名称遵循某些惯例,这些惯例是系统 ABI 的一部分。

命名空间

/svc同样,按照惯例,pkg 命名空间条目会映射到解析组件的软件包。

传出目录

/svc

数据格式

某些命名空间包含带有数据的文件。这些文件使用的数据格式也是系统 ABI 的一部分。例如,组件通过包含 certs.pem 文件的命名空间条目访问根证书。因此,pem 数据格式是系统 ABI 的一部分。

软件包规范

Fuchsia 软件包的目录结构遵循某些命名惯例。这些惯例也是系统 ABI 的一部分。本部分提供了两个重要的打包惯例示例。

Meta

按照惯例,软件包中的 meta 目录包含描述该软件包的元数据文件。

lib

按照惯例,软件包中的 lib 目录包含软件包中的组件使用的共享库。当系统运行软件包中的可执行文件时,系统会相对于此 lib 目录解析对共享库的请求。

Fuchsia 与其他操作系统之间的一个重要区别在于,共享库本身由软件包创建者提供,而非系统本身。因此,共享库本身(包括 libc)不是系统 ABI 的一部分。

系统提供了两个共享库:vDSOVulkan ICD。如需了解详情,请参阅这些部分。

流程结构

Fuchsia 上的进程相当灵活,在很大程度上由进程中运行的可执行文件控制,但进程的某些初始结构是由系统和系统 ABI 的一部分控制的。

如需了解详情,请参阅程序加载

ELF 加载器

Fuchsia 对可执行文件使用 ELF 数据格式。将可执行文件加载到进程时,加载器会将可执行文件的内容解析为 ELF。加载程序会从可执行文件中读取 INTERP 指令,并将该名称解析为可执行文件软件包的 lib 目录中的文件。然后,加载程序会将 INTERP 文件的内容解析为 ELF 共享库,重新定位该库,并将该库映射到新创建的进程中。

启动消息

作为启动进程的一部分,进程的创建者会向进程提供一条消息,其中包含命令行参数、environ、初始句柄以及进程的命名空间等。(传出目录包含在进程的初始句柄集中。)

此消息的格式(包括对命令行参数和 environ 等字段的长度限制)是系统 ABI 的一部分,就像消息内容的规范一样。例如,按照惯例,PWD 环境变量是创建者建议进程用作其当前工作目录的名称。

初始句柄与数字标识符相关联。关于这些标识符的惯例是系统 ABI 的一部分。例如,按照惯例,PA_PROC_SELF 句柄是新创建的进程的进程对象的句柄。除了这些句柄的类型之外,与这些句柄关联的权限也是系统 ABI 的一部分。

VMAR 结构

在启动某个进程之前,创建者会修改该进程的根 VMAR。例如,创建者映射 vDSO 并为初始线程分配堆栈。进程启动时,VMAR 的结构是系统 ABI 的一部分。

作业政策

进程在作业中运行,这些作业可以将政策应用于它们包含的进程和作业。应用于进程的作业政策是系统 ABI 的一部分。例如,组件在 ZX_POL_NEW_PROCESS 设置为 ZX_POL_ACTION_DENY 的进程中运行。这会强制组件使用 fuchsia.process.Launcher 协议创建进程,而不是直接发出 zx_process_create 系统调用。

Vulkan ICD

使用 Vulkan API 实现硬件加速图形的组件将链接到 libvulkan.so,并在其清单中指定 vulkan 功能。此库由包含该组件的软件包提供,因此不属于系统 ABI。不过,libvulkan.so 会加载另一个共享库,名为 Vulkan 可安装客户端驱动程序 (Vulkan ICD)。Vulkan ICD 使用 fuchsia.vulkan.loader.Loader 加载,这意味着库由系统本身提供,而非包含该组件的软件包。因此,Vulkan ICD 是系统 ABI 的一部分。

Vulkan ICD 是一个 ELF 共享库,可正好导出三个符号。这些符号应预留给 Vulkan ICD 使用,不应直接使用。

  • vk_icdGetInstanceProcAddr
  • vk_icdNegotiateLoaderICDInterfaceVersion
  • vk_icdInitializeOpenInNamespaceCallback

此外,Vulkan ICD 共享库还有 NEEDED 部分,其中列出了 Vulkan ICD 所依赖的多个共享库。必须提供包含该组件的软件包才能提供这些共享库。

Vulkan ICD 还会导入许多符号。关于这些导入符号的规范(例如它们的参数和语义)是系统 ABI 的一部分。

目前,NEEDED 部分和 Vulkan ID 导入符号列表都大于我们的预期值。希望我们能够尽量减少系统 ABI 的这些方面。

套接字

数据报取景

用于网络连接的数据报套接字包含一个帧,用于指定与数据报关联的网络地址。此帧也是系统 ABI 的一部分。

终端协议

在终端中运行的程序使用 Fuchsia 终端协议(一种类似于 vt100 的文本协议)与终端进行通信。希望传入 ssh 连接支持此协议的客户端以及希望传出 ssh 连接支持此协议的服务器也会通过 ssh 在网络上公开此协议。