Zircon 系统接口评分准则

Zircon 系统接口表示为 libzircon.so vDSO API Surface。

属于接口的函数的名称必须以 zx_ 开头,预处理器宏的名称也必须以 ZX_ 开头。定义为接口一部分的类型必须具有以 zx_ 开头、以 _t 结尾的名称。

每个属于该接口的函数都必须在 /docs/zircon/syscalls/ 中通过一个 Markdown 文件进行记录,并在 /docs/zircon/syscalls.md 中对其进行链接。

函数名称

函数的名称必须完全由小写字母和下划线组成,并且符合以下语法:

zx_<noun>_<verb>{_<direct-object>}

例如:

zx_handle_close, zx_channel_write, zx_object_signal_peer

通常,名词是内核对象类型,但也可以是其他名词,例如 clockticks,其中没有相应的内核对象。其他函数使用更抽象的名词,例如 systemstatus

名词和动词不得包含下划线(以避免混淆语法)。名词和动词应各自独立的英文单词,但如果无合适的单词或者单词过长,可以使用首字母缩略词(或缩写)。

直接对象可以包含下划线。

有些函数会执行复合操作。在这种情况下,可以通过串联组件操作的名称来命名该函数。

某些函数可对多种类型的内核对象执行操作,在这种情况下,名词是一种更抽象的对象类型。例如,使用名词 object 的函数对大多数内核对象执行操作,使用名词 task 的函数对作业、进程和线程进行操作。

类型

使用 zx_status_t 表示成功和失败。

使用固定大小的整数类型。函数不得使用 shortintunsigned long(或类似类型)。请改用 int16_tint32_tuint64_t 等类型。

使用 size_t 指定缓冲区长度、元素大小和元素计数。

void* 用于指向调用方地址空间中任意类型的指针。对于可能位于其他地址空间中的地址,请使用 zx_vaddr_t / zx_paddr_t

使用 zx_time_t 设置超时,超时必须表示为系统的单调时钟时基(以纳秒为单位)的绝对截止期限。在绝对截止期限没有意义的情况下(例如,计时器延迟),请使用 zx_duration_t 表示以纳秒为单位的时间量,没有特定时基。

参数

接收器

绝大多数函数都作用于句柄,即对内核对象的引用,该类型的内核对象与函数名称中的 noun 匹配。此句柄是此类函数的第一个参数,称为接收器。

为接收器使用 handle 名称。

对象创建函数(例如 zx_channel_createzx_event_create)不能接受句柄参数。这些函数会隐式对当前进程执行操作。

选项参数

函数通常包含一个 options 参数(以允许影响操作的标志),并留出空间,用于在 API 的未来修订版中添加更多标志。

options 参数使用 uint32_t 类型和名称 options

如果存在,options 参数必须是接收方句柄之后的第一个参数;如果函数没有接收器,则是整个第一个参数。

并非所有函数都需要 options 参数。

各个选项值必须定义为预处理器宏,用于将数字字面量转换为 uint32_t。选项必须是可以使用按位 | 运算符组合的位标志。

句柄

将句柄指定为参数时,该函数必须始终使用句柄或从不使用,但以下情况除外:

  • 如果函数接受 options 参数,该函数可能会有一个非默认选项,以避免在各种错误条件下使用句柄。

  • 如果函数不接受 options 参数,则当/它返回 ZX_ERR_SHOULD_WAIT 时,该函数可能会避免使用句柄。

包含数据、计数/大小和/或实际数据的缓冲区

务必为数组或缓冲区提供计数或大小(类型为 size_t),包括字符串。如果缓冲区由该函数写入,则该函数必须具有返回参数,用于返回已写入数据的数量或大小。

对于读写样式操作,缓冲区的指针后面是缓冲区计数或大小;如果可以进行短时间读取或写入操作,输出参数会在操作成功时提供实际计数或大小:

zx_status_t zx_socket_write(zx_handle_t handle, uint32_t options,
                            const void* buffer, size_t size, size_t* actual);

当有多个缓冲区时,缓冲区、长度和输出参数以一致的顺序交错显示。有关示例,请参阅 zx_channel_read

zx_status_t zx_channel_read(zx_handle_t handle, uint32_t options,
                            void* bytes, zx_handle_t* handles,
                            uint32_t num_bytes, uint32_t num_handles,
                            uint32_t* actual_bytes, uint32_t* actual_handles);

输出

out 参数是由函数写入的标量值。例如,一个通过写入 uint32_t 返回 CPU 数量的函数具有 out 参数。如果函数填充了客户端提供的缓冲区,则该缓冲区不是输出参数。

输出参数始终位于参数列表的末尾。

out 参数不能同时是 in 参数。例如,如果某个函数有一个 out 参数,用于返回写入到缓冲区的字节数,则该函数也不得使用该参数来从调用方接收缓冲区的长度。

返回值类型

绝大多数函数的返回类型为 zx_status_t,在成功时为 ZX_OK,在失败时为 ZX_ERR_...

请勿通过 zx_status_t 返回其他值(例如使用正值范围)。请改用 out 参数。

其他返回值类型可用于不会失败的函数。例如,zx_thread_exit 永远无法退出线程,并且返回类型为 void。 同样,zx_clock_get_monotonic 不能获取当前时间,并且返回类型为 zx_time_t

特定于函数的规则

zx_object_get_property 与 zx_object_get_info

有两种类似的公开对象数据的机制:zx_object_get_propertyzx_object_get_info。如果 (a) 可以使用 zx_object_set_property 设置该属性,或 (b) 该属性存在于多种类型的对象中,则优先通过 zx_object_get_property 公开数据。在其他情况下,可考虑针对具有该属性的对象类型将相关数据包含在常规 zx_object_get_info 主题中。