Zircon 是一种基于对象的内核。用户模式代码几乎只通过对象句柄与操作系统资源进行交互。句柄可以视为一个活跃会话,其特定操作系统子系统的范围限定为特定资源。
Zircon 会主动管理以下资源:
- 处理器时间
- 内存和地址空间
- 设备 I/O 内存
- 中断
- 信号和等待
- 进程间通信
应用的内核对象
IPC
任务
调度
信号
内存和地址空间
正在等待
驱动程序的内核对象
内核对象生命周期
内核对象是受引用计数的。大多数内核对象都是在“create”系统调用期间创建的,并由第一个句柄保持活动状态(作为创建系统调用的输出)。调用方会获取句柄的数字 ID,并且句柄本身位于进程的句柄表中。
只要句柄存在于句柄表中,相应句柄就会一直保持活动状态。句柄通过以下方式从句柄表中移除:
通过
zx_handle_close
关闭它们,这会减少相应内核对象的引用计数。通常,当最后一个句柄关闭时,内核对象引用计数将达到 0,这会导致内核对象被销毁。当拥有包含句柄的未读消息的通道端点被销毁时,所有待处理的消息也会被销毁,同时关闭消息中包含的所有句柄。
拥有句柄表的进程被销毁时。内核会有效地迭代整个句柄表,然后依次关闭每个句柄。
通过 zx_handle_duplicate
创建新句柄(引用同一对象)以及获取直接指针引用(被某些内核代码)时,引用计数会增加;因此,内核对象的生命周期可能会长于创建该引用的代码的生命周期。此外,还会保留引用对象的活动句柄计数,从而允许内核在对象的句柄计数为零时触发特定行为,即使内核因直接指针引用而让对象保持活跃状态也是如此。
内核对象在没有未处理的句柄的情况下会保持活动状态,具体有三种重要情况:
该对象由未使用的消息中的句柄引用。这可以通过 channel API 实现。当此类句柄位于通道中时,内核会使对象保持活动状态,并且有效句柄计数为非零。
此对象是另一个处于活动状态的对象的父对象。附加到实时 VMAR、具有实时线程的进程和具有实时进程或子作业的作业的 VMO 就属于这种情况。
线程由调度器保持活跃状态。处于活跃状态的线程将继续存在,直到其通过调用
zx_thread_exit
主动退出或通过zx_task_kill
终止进程。
最后一种情况的结果是,单个线程可以使其进程和整个作业沿袭(直到根作业为止)保持活跃状态。
对等互连的对象和对等方关闭状态
目前,内核将以下对象类型定义为“对等”对象。
名称 | 对等关闭的信号名称 |
---|---|
声道 | ZX_CHANNEL_PEER_CLOSED |
套接字 | ZX_SOCKET_PEER_CLOSED |
先进先出 (FIFO) | ZX_FIFO_PEER_CLOSED |
事件配对 | ZX_EVENTPAIR_PEER_CLOSED |
所有对等互连的对象成对创建,这些对象在对等关系中相互关联。当对等互连对象的活动句柄计数达到 0 时,如果该对象仍存在指向其对等项的链接,对等对象将处于 PEER_CLOSED
状态,从而导致链接被销毁,特定的 ZX_*_PEER_CLOSED
信号在对等方上变为断言状态,并且涉及该对象对等方的系统调用(例如 zx_channel_write
)也会返回错误 ZX_ERR_PEER_CLOSED
。
当某个对象的最终句柄通过调用 zx_handle_close
或 zx_handle_close_many
关闭时,可以保证在 zx_handle_close
系统调用从内核返回之前,该对象的对等方(如果有)将被置于 PEER_CLOSED
状态,并在此过程中断言其关联信号。
请注意,当对象对等的活跃句柄计数达到零时,即使对等对象因内核持有直接指针引用而继续存活,对象也会放入 PEER_CLOSED
中。
内核对象安全性
内核对象没有固有的安全概念,也不会执行授权检查;每个句柄都拥有安全权。单个进程可以有两个针对同一对象的不同句柄,但这些句柄具有不同的权限。