摘要
创建虚拟机对象的子级。
声明
#include <zircon/syscalls.h>
zx_status_t zx_vmo_create_child(zx_handle_t handle,
uint32_t options,
uint64_t offset,
uint64_t size,
zx_handle_t* out);
说明
zx_vmo_create_child() 会创建一个新的虚拟内存对象 (VMO),该对象是现有 VMO 的子对象。语义的行为取决于子项的类型。
成功时返回一个句柄,表示具有请求大小的对象。
选项必须包含以下标志之一,以指定子类型:
ZX_VMO_CHILD_SNAPSHOT- 创建一个行为类似于执行热切复制的子级。发生写入时,父进程和子进程都会执行延迟复制。延迟复制允许子级和父级彼此分叉。从父 VMO 大小范围之外的范围进行的任何读取都包含零,而写入会分配新的零填充页面。如果使用ZX_VMO_CHILD_NO_WRITE而不是ZX_VMO_CHILD_RESIZABLE创建,则会创建不可变的 VMO。
以下情况不支持此标志:
- 具有固定区域的 VMO。
- 使用 zx_vmo_create_physical() 或 zx_vmo_create_contiguous() 创建或派生自 zx_vmo_create_physical() 或 zx_vmo_create_contiguous() 的 VMO
- 由用户分页器支持的 VMO。
如需了解 VMO 系统调用与子项的互动,请参阅备注。
ZX_VMO_CHILD_SNAPSHOT_AT_LEAST_ON_WRITE- 创建一个具有至少写入时复制语义的子级。对子级进行的任何写入操作都会从父级中引入相应网页的副本,之后其内容可能会与父级不同。在写入页面并复制之前,允许(但不保证)读取返回更改的值(如果父级执行写入操作)。此标志不得用于通过zx_vmo_create_physical()、zx_vmo_create_contiguous()创建的 VMO 或此类 VMO 的后代。如需了解 VMO 系统调用与子项的互动,请参阅备注。ZX_VMO_CHILD_SNAPSHOT_MODIFIED- 创建一个子级,该子级的行为就像对父级中不受分页器支持的任何页面(即已由受分页器支持的 VMO 的子级修改的页面)执行了急切复制一样。基于分页器的页面将至少具有写入时复制语义。此标志不得用于通过zx_vmo_create_physical()、zx_vmo_create_contiguous()创建的 VMO、包含固定内存页的 VMO 或此类 VMO 的后代。对于使用SNAPSHOT_AT_LEAST_ON_WRITE创建的任何具有非 slice 子对象的 VMO 或不是由分页内存支持的 VMO 的子对象,也不支持此标志。 如需了解 VMO 系统调用与子项的互动,请参阅备注。ZX_VMO_CHILD_REFERENCE- 创建对 VMO 的引用。对参考 VMO 的所有操作都如同对父对象执行一样。引用始终涵盖整个父级,并且 offset 和 size 必须为 0。如果用户希望通过使用ZX_VMO_ZERO_CHILDREN信号来跟踪对 VMO 的未完成引用,则此方法非常有用。如需详细了解此信号,请参阅备注。 此标志不得用于通过zx_vmo_create_physical()、zx_vmo_create_contiguous()创建的 VMO 或此类 VMO 的后代。ZX_VMO_CHILD_SLICE- 创建一个可直接读写父级一部分的切片。切片与引用的不同之处在于,它仅允许访问父 VMO 的子范围,并且支持不同的父 VMO 类型:ZX_VMO_CHILD_SLICE可用于使用zx_vmo_create_physical()或zx_vmo_create_contiguous()创建的 VMO 及其后代。此标志不得与使用ZX_VMO_RESIZABLE选项创建的 VMO 搭配使用。
此外,options 可以包含以下零个或多个标志,以进一步指定子级的行为:
ZX_VMO_CHILD_RESIZABLE- 创建可调整大小的子 VMO。这与ZX_VMO_CHILD_SLICE不兼容。ZX_VMO_CHILD_NO_WRITE- 创建无法写入的子级。这与ZX_VMO_CHILD_RESIZABLE不兼容。
偏移量必须与页面对齐。
偏移量 + 大小不得超出 64 位无符号值的范围。
偏移量和大小都可以从原始 VMO 的大小开始或扩展到原始 VMO 的大小之外。
VMO 的大小将向上舍入到下一个页面大小边界。
VMO 的内容大小将初始化为给定的(未舍入)大小。将 zx_object_get_property() 与 ZX_PROP_VMO_CONTENT_SIZE 搭配使用,以读取 VMO 的内容大小。将 zx_object_set_property() 与 ZX_PROP_VMO_CONTENT_SIZE 搭配使用,可设置 VMO 的内容大小,而无需实际调整 VMO 的大小。
默认情况下,子句柄的权限与原始句柄的权限相同,但有少数例外情况。如需详细了解各项权利,请参阅 zx_vmo_create()。
如果 options 包含 ZX_VMO_CHILD_RESIZABLE,则会添加 ZX_RIGHT_RESIZE。
对于 ZX_VMO_CHILD_REFERENCE,ZX_VMO_CHILD_RESIZABLE 选项用于控制是否可以使用 out 中返回的引用句柄调整父 VMO 的大小。如果父 VMO 可调整大小,则无论是否存在 ZX_VMO_CHILD_RESIZABLE,引用都会看到父 VMO 的大小调整。不过,只有当父 VMO 可调整大小时,才支持 ZX_VMO_CHILD_RESIZABLE,也就是说,无法创建不可调整大小的 VMO 的可调整大小的引用。
在所有情况下,如果设置了 ZX_VMO_NO_WRITE,则会移除 ZX_RIGHT_WRITE。
如果 options 为 ZX_VMO_CHILD_SNAPSHOT、ZX_VMO_CHILD_SNAPSHOT_AT_LEAST_ON_WRITE 或 ZX_VMO_CHILD_SNAPSHOT_MODIFIED,且未设置 ZX_VMO_CHILD_NO_WRITE,则系统会添加 ZX_RIGHT_WRITE 并移除 ZX_RIGHT_EXECUTE。
备注
创建子 VMO 会导致现有(源)VMO ZX_VMO_ZERO_CHILDREN 信号变为非活动状态。只有当最后一个子进程被销毁且这些子进程在地址空间中没有映射时,ZX_VMO_ZERO_CHILDREN 才会再次变为有效。
非 slice 子 VMO 将通过以下方式与 VMO 系统调用进行交互:
- 子级
zx_vmo_op_range()的提交模式会将页面提交到子级,这些页面与父级的相应页面具有相同的内容。如果这些页面由分页器提供,此操作也会提交父级中的这些页面。否则,如果这些页面未在父级中提交,则会直接将填充零的页面提交到子级,而不会影响父级。 - 不支持
zx_vmo_op_range()的 DECOMMIT 模式。
权限
handle 必须是 ZX_OBJ_TYPE_VMO 类型,并且具有 ZX_RIGHT_DUPLICATE 和 ZX_RIGHT_READ。
返回值
zx_vmo_create_child() 在成功时返回 ZX_OK。如果失败,则返回负错误值。
错误
ZX_ERR_BAD_TYPE 输入句柄不是 VMO。
ZX_ERR_ACCESS_DENIED 输入源句柄的权限不足。
ZX_ERR_INVALID_ARGS out 是无效指针或 NULL,或者偏移量未与页面对齐,或者给定的 options 组合不兼容。
ZX_ERR_OUT_OF_RANGE offset + size 过大。
ZX_ERR_NO_MEMORY 因内存不足而导致的失败。
用户空间无法妥善处理此(不太可能发生的)错误。
在未来的 build 中,此错误将不再发生。
ZX_ERR_BAD_STATE 无法创建 COW 子级,因为 VMO 具有一些固定页面。
ZX_ERR_NOT_SUPPORTED 输入句柄是可舍弃的 VMO,或者输入句柄是可调整大小的 VMO,且 options 包含 ZX_VMO_CHILD_SLICE。