添加新的 Zircon 系统调用(或新的 Zircon 对象类型)

本文档简要介绍了如何添加新的 Zircon 系统调用。目标受众群体是内核开发者或添加新系统调用的任何人。

请注意,本指南仅介绍了添加系统调用/对象的机制。它不是样式指南或评分标准,也不会提供有关如何确定 API 何时足够稳定或成熟以成为系统接口一部分的任何建议。

由于我们的系统会不断变化,因此本指南可能会过时。抱歉。如果您在按照本指南操作时发现错误或遗漏,请尝试更新本指南。谢谢!

概览

您可以通过多种方式构建更改,以添加新的 Zircon 系统调用 (或对象)。本指南将介绍一种方法,其中包含四个 CL:桩、实现、extra 和注解。

我们将采用“重写历史记录”方法。Zircon 系统调用(目前)不遵循平台版本控制,因此我们将使其看起来像是新系统调用一直存在。为此,我们需要更新已冻结 API 级别的部分 SDK 历史文件。

桩 CL:从 HEAD 处的桩开始

在此 CL 中,您将定义系统调用并提供一个仅返回 ZX_ERR_NOT_SUPPORTED 的桩实现。请务必在此桩 CL 中添加一个核心测试,用于验证调用方是否会崩溃,以及新调用是否会按预期返回错误。

构建系统和 FIDL 编译器会自动为您生成一些样板代码。为了充分利用此功能,您应养成在对 FIDL 文件进行更改后执行默认 build fx build 并运行 fx check-goldens 的习惯。

为说明这一点,我们来看看一个同时添加了新的 Zircon 对象 (counter) 和新的系统调用 (zx_counter_create) 的桩 CL

桩 CL 包含四个部分。

1. 使用 FIDL 定义系统调用

接下来,在现有 .fidl 文件中定义新的系统调用,或根据需要添加新文件。请务必添加注释掉的 @available(added=HEAD) 注解,指明在 HEAD 中添加了新的系统调用(如果添加了新的 Zircon 对象,则添加了对象)。

在极少数情况下,如果要添加新的 Zircon 对象,您需要执行一些额外的步骤。

a. 告知 FIDL 编译器新对象类型。FIDL 工具链内置了对象类型的相关知识。这并不优雅,但可以避免一些循环依赖项。您必须更新 FIDL 工具链的部分内容,才能了解新对象类型。具体而言,请更新:

b. 按照构建时收到的构建错误中提供的说明更新 fidlc 金标准。

c. 将新对象类型添加到 zircon/types.h

d. 更新 //sdk/history/*/zx.api_summary.json 文件。这些是适用于公共 zx FIDL 库的,该库与系统调用库共享 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. 添加 core-test

添加一个核心测试,用于验证桩是否返回正确的错误值(并且不会使系统崩溃)。通过在此测试中使用新的 lib/zx 封装容器,您可以确保它也按预期运行。

将桩构建并通过 CQ 后,将其提交。接下来,进入实现 CL。

实现 CL:填充桩

现在,是时候将桩实现替换为真实实现,添加真实测试和真实文档了。构建完成,通过 CQ 审核,发布,然后继续。

额外 CL:添加其余内容

获得使用 C/C++ 绑定的有效实现后,您现在可以添加 Rust 绑定并更新 (fidl_codec(由 fidlcat 使用): - display_handle.cc 中的 ShortObjTypeName - printer.cc 中的 PrettyPrinter::DisplayObjType

上述“extras”列表可能不完整,因此现在是时候查看其他广告和系统调用,看看是否还有其他需要更新的内容(工具?其他语言的绑定?)。提交 extras CL,然后进入最后一步。

注释 CL:将 HEAD 更改为 NEXT

现在,实现和 extra 已到位,请返回并将您在 @availableZX_AVAILABLE_SINCE 注解中添加的值从 HEAD 更改为 NEXT,以便在下一个稳定 API 级别中提供该系统调用。