FIDL概述
本文档的目的是用来描述Fuchsia接口定义语言(FIDL)的高层目标与需求。 <!—
Related Documents
- FIDL: Wire Format Specification
- FIDL: Language Specification
- FIDL: Compiler Specification
- FIDL: C Language Bindings
- FIDL: C++ Language Bindings
- FIDL Examples: Some small example code used during development
- FIDL Tutorial: A tutorial on using FIDL services in several languages
相关文档
- FIDL: 有线格式规范
- FIDL: 语言规范
- FIDL: 编译规范
- FIDL: 绑定C语言(英文原文)
- FIDL: 绑定C++语言(英文原文)
- FIDL示例:用于开发使用的一些示例代码片段
- FIDL教程(英文原文):关于在多种语言中使用FIDL服务的教程
概述
Fuchsia接口定义语言(FIDL)是用来描述Fuchsia操作系统中进程间通信协议(IPC)的语言。FIDL的工具链(编译器)和运行时支持库(绑定)用于帮助开发者高效的使用IPC。
目标
由于Fuchsia是微内核操作系统,其中大部分的功能在用户空间中实现,包括设备驱动等特权组件,所以它大量地依赖IPC进行通信。因此,IPC机制在设计上必须具有高效性、确定性、稳健性和易用性。
IPC的高效性衡量生成、传输和处理进程间消息所需的计算开销。IPC将参与所有的系统操作,所以它必须高效。FIDL的编译器必须生成紧凑的代码,没有额外的间接跳转或者隐形开销。最重要的是,它应该至少要你特定优化的代码一样好。 IPC的确定性衡量在已知的封装资源大小的执行事务能力。IPC将被广泛的用于关键系统服务,例如,服务于许多客户端的文件系统,必须按照可预测的方式进行工作。FIDL的有线格式必须对确保结构体大小与布局的不变性提供强静态保证,从而减轻对动态内存分配或复杂验证规则的需求。
IPC的鲁棒性衡量考虑IPC作为操作系统ABI的重要组成部分的需要。保持二进制的稳定性至关重要,协议演变的机制必须谨慎设计,以便使现在的服务与他们的客户端不违反不变性,特别是在确定性的需求也被考虑其中时。FIDL的绑定也必须高效,轻量并且经过严格验证。
IPC的易用性衡量IPC协议作为操作系统API的重要组成部分,为通过IPC访问服务提供好的开发者使用方法是很重要的。FIDL的代码生成器减轻了手工编写IPC绑定代码的负担。此外,FIDL的代码生成器可以提供不同的绑定来适应不同开发者以及他们的习惯。 TODO: 解释为满足不同受众使用合适的定制化绑定的目标是什么,例如,本地系统编程 vs.事件驱动调度 vs. 异步调用等… 以及关于更多FIDL的介绍,例如系统API,SDK的关注点等。
需求
目的
- 描述用于Zircon上使用的IPC协议的数据结构与接口。
- 针对特定于进程间通信的优化; FIDL不能用于磁盘上的持久化操作或者跨设备的网络传输。
- 同一设备上进程间的有效传输消息由数据(字节)与Zircon中处理通道的能力组成。
- 专为促进Zircon原语的有效使用而设计;不打算在其它平台上使用,并且不可移植。
- 为创建、发送、接收与消费消息提供方便的API。
- 执行足够的验证来维护协议不变性(并仅是如此而已)。
性能
- 与使用手动定义数据的方式一样(在速度与内存使用上)高效。
- 在有线格式上,使用未压缩的本地主机大小端数据类型,并纠正数据对齐来支持消息内容的原地访问。
- 如果消息大小静态已知或者有界时,无需分配动态内存以产生或消费消息。
- 利用move-only语义来显式处理所有权
- 数据结构打包顺序是规范的,无歧义的,并且是最小对齐的。
- 避免反向修改指针。
- 避免高性能损耗的验证操作。
- 避免可能栈溢出的计算。
- 将接口请求流水化实现异步操作。
- 结构体固定大小;将可变大小的数据存储在外部。
- 结构体不能自描述;FIDL文件用于描述结构体的内容。
- 结构没有版本控制,但是接口可扩展新的方法来演化协议。
人类工程学
- Fuchsia团队维护的编程语言绑定:
- C, C++ (native), C++ (idiomatic), Dart, Go, Rust
- 同时留意我们希望去支持更多语言,例如:
- Java, Javascript, etc.
- 绑定与代码生成根据原定的用途适应原有的风格。
- 在编译时生成代码,优化消息序列,反序列化,并且验证。
- FIDL语法是熟悉的,易于访问的,并且编程语言不可知。
- FIDL提供一个库来简化其它开发者的部署与使用。
- FIDL表述系统API所需要的最常见的数据类型;它不寻求提供支持所有编程语言一对一的全面映射。
实现
编译器使用C++编写,用于Zircon中的组件使用。
编译器是可移植的,并可利用宿主工具链来构建它。
我们不会在Fuchsia以外的平台支持FIDL绑定。
代码在什么位置?
规范的组成部分
FIDL传输格式
FIDL有线格式规范了FIDL消息是如何在内存中表示以支持IPC传输。
FIDL语言
FIDL语言是fidl文件来描述接口的语法。
FIDL编译器
FIDL编译器的功能是为使用与实现FIDL语言描述的接口的程序生成代码。
FIDL绑定
FIDL绑定是语言特定的运行时支持库与代码生成器,以提供用于操作FIDL数据结构和接口的API。
语言相关的主题:
绑定的风格根据语言而有所不同:
- 本地绑定: 为高度敏感的上下文,如设备驱动与高吞吐量的服务器而设计,充分利用原地访问,避免内存分配,但是需要开发者了解更多关于协议上的限制。
- 惯用绑定: 通过将数据从有线格式拷贝到易于使用的数据类型上(例如堆上字符串或者向量),来提供更开发者友好的放好似,但是这种方式对应的效率较低。
绑定提供了根据不同语言调用接口的多种方法:
- 发送/接收: 直接通过channel读写消息,无内置等待循环(C)
- 基于回调: 异步分配的方式接收消息,并作为事件循环的回调(C++,Dart)
- 基于端口: 接收的消息传递到port或future上(Rust)
- 同步调用: 等待应答后返回结果(Go,C++单元测试)
绑定提供以下主要操作的部分或全部:
- 编码: 将本地数据结构原地转换为有线格式(与验证相结合)
- 解码: 将有线格式原地转换为本地数据结构(与验证相结合)
- 复制/移动到惯用形式: 把本地数据结构的内容复制为惯用数据结构中,同时移除handle。
- 复制/移动到本机格式: 把惯用数据结构的内容复制为本地数据结构中,同时移除handle。
- 克隆: 复制本地或惯用数据结构 (不包含只可移动的类型)
- 调用: 调用接口方法
工作流
本章节介绍了使用FIDL描述IPC协议的作者,发布者,使用者的工作流。
创作 FIDL
基于FIDL协议的作者创建一个或多个fidl文件来描述他们的数据结构与接口。
作者将FIDL文件分组为一个或多个FIDL库。每个库表示一组逻辑相关的功能,并具有唯一命名。在同一个库中的FIDL文件可以访问库中所有其它的声明,并且FIDL文件中的声明顺序并不重要。
一个FIDL库中的FIDL文件通过importing声明可以访问另一个库中的模块。导入其它库使得它们的符号可供使用,从而可以构建它们的派生协议。导入的符号必须通过库名或别名来限定,以防止命名空间冲突。
发布 FIDL
基于FIDL协议的发布者负责向使用者提供FIDL库。例如,作者可以在公共源仓库中分发FIDL库,或者将他们以SDK中的一部分的方式进行分发。
使用者只需向FIDL编译器指定包含FIDL库文件的目录(以及它们的依赖项)。这项工作的具体细节通常将由使用者的构建系统来解决。
使用FIDL
基于FIDL的协议使用者利用FIDL编译器生成适用于他们语言运行时特定绑定的代码。对于某些语言运行时,使用者可以选择几种不同风格来生成代码,他们可以有线格式上互操作,但可能在源码级别上可能不行。
在Fuchsia的构建环境中,从FIDL库生成代码将自动为每个相关的语言通过每个FIDL构建目标自动完成。
在Fuchsia的SDK环境中,从FIDL库中生成代码的过程将作为编译使用他们的应用程序的构建过程一部分。