本文档是有关添加新 Zircon 系统调用的简短指南。目标受众群体是内核开发者或任何添加新系统调用的人员。
请注意,本指南仅介绍添加系统调用/对象的机制。它不是样式指南或评分标准,也不会就如何判断 API 是否足够稳定或足够成熟以成为系统接口的一部分提供任何建议。
由于我们的系统在不断变化,因此本指南可能会过时。抱歉。如果您在遵循本指南时发现错误或遗漏,请尝试进行更新。谢谢!
如果您要更改现有系统调用使用的结构体,而不是添加新的系统调用,请参阅对系统调用结构体进行版本控制。如果您的新系统调用接受或返回结构体,请为调用方提供一种指定结构体版本的方法(例如 options 中的主题或版本位),以便结构体日后可以演进。
概览
您可以通过多种方式来构建更改,以添加新的 Zircon 系统调用(或对象)。本指南将介绍一种由四个 CL 组成的方法:桩、实现、额外内容和注解。
我们将采用“重写历史记录”方法。Zircon 系统调用(目前)不遵循平台版本控制,因此我们将让新系统调用看起来好像一直存在。为此,我们需要更新一些 SDK 历史记录文件,以反映冻结的 API 级别。
桩 CL:从 HEAD 处的桩开始
在此 CL 中,您将定义系统调用并提供一个仅返回 ZX_ERR_NOT_SUPPORTED 的桩实现。请务必在此桩 CL 中添加核心测试,以验证调用方不会崩溃,并且新调用会按预期返回错误。
构建系统和 FIDL 编译器会自动为您生成一些样板。为了充分利用这一优势,您需要养成在更改 FIDL 文件后执行默认构建 fx build 并运行 fx check-goldens 的习惯。
为了说明这一点,我们来看一个桩 CL,它同时添加了一个新的 Zircon 对象 (counter) 和一个新的系统调用 (zx_counter_create)。
桩 CL 包含四个部分。
1. 使用 FIDL 定义系统调用
接下来,在现有 .fidl 文件中定义新的系统调用,或根据需要添加新文件。请务必添加注释掉的 @available(added=HEAD) 注解,以指明新的系统调用(或对象,如果要添加新的 Zircon 对象)是在 HEAD 处添加的。
在极少数情况下,如果您需要添加新的 Zircon 对象,则需要执行一些额外的步骤。
a. 让 FIDL 编译器了解新的对象类型。FIDL 工具链内置了对象类型知识。这虽然不够优雅,但可以避免一些循环依赖项。您必须更新 FIDL 工具链的某些部分,才能理解新的对象类型。具体而言,请更新:
//tools/fidl/fidlc/src/properties.h中的HandleSubtype//tools/fidl/fidlc/src/names.cc中的NameHandleSubtype//tools/fidl/abi-compat/src/compare/handle.rs中的HandleType//tools/fidl/fidlc/schema.json中的handle-subtype//tools/fidl/fidlc/tests/types_tests.cc中的GoodHandleSubtype//tools/fidl/lib/fidlgen/types.go中的HandleSubtype和ObjectType常量//tools/fidl/fidlgen_rust/codegen/ir.go中的handleSubtypes、handleSubtypesFdomain和objectTypeConsts
b. 按照在未更新 fidlc 黄金文件的情况下进行构建时收到的构建错误中提供的说明,更新这些黄金文件。
c. 将新的对象类型添加到 zircon/types.h。
d. 更新 //sdk/history/*/zx.api_summary.json 文件。这些文件适用于公共 zx FIDL 库,该库与 syscall 库共享 zx_common.fidl。
e. 根据需要扩展 docsgen。
2. 在内核中实现系统调用
在 zircon/kernel/lib/syscalls/ 中的某个位置实现系统调用,并使用前缀 sys_ 而不是 zx_。目前,该实现应仅返回 ZX_ERR_NOT_SUPPORTED。
3. 添加 lib/zx C++ 封装容器
添加新的 lib/zx 封装容器或扩展现有 lib/zx 封装容器,以便为新的系统调用提供 C++ API。请务必向新的 C++ 方法(或类,如果是新的 Zircon 对象)应用 ZX_AVAILABLE_SINCE(HEAD) 注解。虽然系统调用本身似乎从一开始就存在,但 C++ 封装容器是在 HEAD 中添加的。
4. 添加核心测试
添加核心测试,以验证桩是否返回正确的错误值(并且不会导致系统崩溃)。通过在此测试中使用新的 lib/zx 封装容器,您可以确保它也能按预期运行。
在桩成功构建并通过 CQ 后,将其提交。接下来,继续查看实现 CL。
5. 为新的 Zircon 对象添加 FIDL 语言绑定
如需在 C++ 和 Rust 语言绑定中启用新的 Zircon 对象(即 zx.Handle:COUNTER),还必须更新其他几个方面。这些更新可让语言绑定代码生成器知道如何处理新的 Zircon 对象。
对于 FIDL C++ 语言绑定,请更新:
//src/lib/fidl_codec/display_handle.cc中的ShortObjTypeName//src/lib/fidl_codec/printer.cc中的DisplayObjType- 向
//sdk/lib/fidl/hlcpp/include/lib/fidl/cpp/internal/header.h添加对象标头 //tools/fidl/lib/fidlgen_cpp/handles.go中的handleSubtypeConsts//tools/fidl/lib/fidlgen_cpp/name_transforms.go中的zxNames
对于 FIDL Rust 语言绑定,请更新:
//sdk/rust/zx/src/handle.rs中的ObjectType//src/lib/fuchsia-async/src/handle/mod.rs中的invoke_for_handle_types
实现 CL:填充桩
现在,可以将桩实现替换为实际实现,并添加实际测试和实际文档。构建、通过 CQ、落地,然后继续。
Extras CL:添加其余内容
在通过 C/C++ 绑定实现正常运行后,您现在可以添加 Rust 绑定,并更新 (fidl_codec(由 fidlcat 使用):
- display_handle.cc 中的 ShortObjTypeName
- printer.cc 中的 PrettyPrinter::DisplayObjType
上述“额外”列表可能不完整,因此现在是时候查看其他系统调用,看看是否还有更多需要更新的内容(工具?其他语言的绑定?)。提交 extra CL 并继续执行最后一步。
Annotations CL: Change HEAD to NEXT
现在,实现和 extra 已落地,请返回并将您在 @available 和 ZX_AVAILABLE_SINCE 注解中添加的值从 HEAD 更改为 NEXT,以便在下一个稳定 API 级别中提供系统调用。