Zircon 是一个基于对象的内核。用户模式代码几乎完全通过对象句柄与操作系统资源进行交互。句柄可视为一个有效会话,其特定操作系统子系统的范围限定为特定资源。
Zircon 会主动管理以下资源:
- 处理器时间
- 内存和地址空间
- device-io 内存
- 中断
- 信号和等待
- 进程间通信
适用于应用的内核对象
常规
IPC
任务
Scheduling
信号
内存和地址空间
正在等待
适用于驱动程序的内核对象
内核对象生命周期
内核对象是引用计数的。大多数内核对象是在“创建”系统调用期间创建的,并由第一个句柄保持活跃状态(作为创建系统调用的输出提供)。调用方会获取句柄的数字 ID,而句柄本身会放置在进程的句柄表中。
只要句柄存在于句柄表中,系统就会将其保持有效状态。句柄会通过以下方式从句柄表中移除:
通过
zx_handle_close
关闭它们,这会递减相应内核对象的引用计数。通常,关闭最后一个句柄后,内核对象引用计数将达到 0,这会导致内核对象被销毁。当包含手柄的未读消息的频道端点被销毁时,所有待处理消息也会被销毁,同时关闭消息中包含的所有手柄。
当拥有句柄表的进程被销毁时。内核会有效地迭代整个句柄表,依次关闭每个句柄。
通过 zx_handle_duplicate
创建新的句柄(引用同一对象)时,引用计数会增加,但获取直接指针引用(通过某些内核代码)时也会增加;因此,内核对象的生命周期可能会比创建它的代码的生命周期更长。系统还会维护一个单独的引用某个对象的有效句柄计数,以便在对象的句柄计数达到零时触发特定行为,即使内核因直接指针引用而将对象保持在后台活动状态也是如此。
在以下三种重要情况下,即使没有任何有效的句柄,内核对象也会保持活跃状态:
对象被消息中的句柄引用,但该消息尚未被使用。这可以通过渠道 API 实现。当此类句柄位于该通道中时,内核会让对象保持有效状态,并且有效句柄数不为零。
该对象是另一个处于活动状态的对象的父对象。例如,对于挂接到实时 VMAR 的 VMO、具有实时线程的进程,以及具有实时进程或子作业的作业。
线程由调度程序保持活跃状态。处于活动状态的线程将一直保持活动状态,直到它通过调用
zx_thread_exit
自行退出或进程通过zx_task_kill
终止为止。
最后一种情况的结果是,单个线程可以让其进程以及从根作业开始的整个作业谱系保持活跃状态。
对等对象和对等关闭状态
目前,内核将以下对象类型定义为“对等”对象。
名称 | 对等关闭信号名称 |
---|---|
声道 | ZX_CHANNEL_PEER_CLOSED |
Socket | 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
,即使对等对象因内核持有的直接指针引用而继续存在也是如此。
内核对象安全
内核对象没有内在的安全概念,也不执行授权检查;安全权利由每个句柄持有。单个进程可以对同一对象拥有两个不同的句柄,并且具有不同的权限。