RFC-0013:克隆 VMO 映射 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 一个系统调用,用于根据映射创建 VMO 的 CoW 克隆,而无需为其添加句柄。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2020-10-26 |
审核日期(年-月-日) | 2020-12-09 |
摘要
目前,只有当您拥有 VMO 的句柄时,才能创建 VMO 的 CoW 克隆。 这对于 zygote 用例是不够的, 这需要 CoW 克隆整个地址空间, 包括所有 VMO 句柄都已关闭的映射。 此 RFC 提出了新的系统调用来解决这一问题。
动机和问题陈述
Linux 上的 Chromium 通过从 Zygote 进程派生渲染程序来生成渲染程序, 从而节省大量内存和 CPU 我们希望能在 Fuchsia 上节省资金。
为此,我们需要通过某种方式实现“地址空间克隆”操作, 如果给定,则会发生以下情况:
- 进程根 VMAR
- 一些句柄引用了在地址空间中映射的 VMO
将返回:
- 一个新进程,其地址空间由输入进程中映射的 VMO 的克隆填充
- 对于输入过程中引用 VMO 的每个句柄, 一个新句柄,用于引用新进程中相应 VMO 的克隆
通过添加此系统调用,我们可以轻松在用户空间中实现这一点。
可通过使用 ZX_INFO_PROCESS_MAPS
获取地址空间布局来做到这一点。
并使用 zx_vmar_create_vmo_child
为每个映射创建克隆,
但有句柄的 VMO 除外
均使用 zx_vmo_create_child
处理。
设计
zx_vmar_create_vmo_child
zx_status_t zx_vmar_create_vmo_child(zx_handle_t handle,
uint32_t options,
zx_vaddr_t addr,
size_t size,
zx_handle_t* out)
为 addr
到 addr
+size
范围中映射的网页创建 CoW 克隆
(位于 handle
引用的 VMAR 中)。
该范围必须是单个 VMO 映射的子范围,
也就是说,它不能跨越两个映射,也不能包含任何未映射的页面。
结果会生成一个新的 VMO,它是范围内映射的 VMO 的子项。
允许的选项包括
ZX_VMO_CHILD_SNAPSHOT
、ZX_VMO_CHILD_SNAPSHOT_AT_LEAST_ON_WRITE
和ZX_VMO_CHILD_NO_WRITE
。
它们的解释与 zx_vmo_create_child
中的解释相同。
(出于安全方面的考虑,目前不允许使用 ZX_VMO_CHILD_SLICE
:
必须特别注意
修改父级 VMO 的功能不会打破任何安全边界。)
在以下情况下返回 ZX_ERR_INVALID_ARGS
:
- 范围
addr
到addr
+size
不是单个 VMO 映射的子范围 addr
或size
未页面对齐
在以下情况下返回 ZX_ERR_ACCESS_DENIED
:
- 映射是使用新标志
ZX_VM_CANNOT_CREATE_VMO_CHILD
完成的, 或者 vmar 选项包含此标志 handle
未提供ZX_RIGHT_INSPECT
如果 handle
不是有效的句柄,则返回 ZX_ERR_BAD_HANDLE
;
ZX_ERR_WRONG_TYPE
(如果 handle
不是 VMAR),
如果 VMAR 被销毁,则为 ZX_ERR_BAD_STATE
。
如果记录的原因适用,还可以返回 zx_vmo_create_child
返回的任何错误。
返回的 VMO 句柄将包含 ZX_DEFAULT_VMO_RIGHTS
,并发生以下更改:
- 如果指定了
ZX_VMO_CHILD_NO_WRITE
,系统将移除ZX_RIGHT_WRITE
。 - 如果映射可执行且未指定
ZX_VMO_CHILD_NO_WRITE
,则系统会添加ZX_RIGHT_EXECUTE
。 这意味着,您可以创建可执行映射的可执行克隆, 但它们必须是只读的
ZX_VM_CANNOT_CREATE_VMO_CHILD
ZX_VM_CANNOT_CREATE_VMO_CHILD
是新的 zx_vm_options_t
标志
可为 VMO 映射或 VMAR 指定
这允许映射 VMO 或创建 VMAR 的代码
以禁止对它们执行 zx_vmar_create_vmo_child
操作。
实现
添加系统调用并不复杂;可以在一个 CL 中完成。 克隆算法的实现超出了此 RFC 的范围。
性能
不值得单独对此系统调用进行基准化分析, 因为它仅适用于 zygote 实现。 我们应该衡量 zygote 实现的整体性能。
安全注意事项
目前无法使用 VMAR 引用(而不是句柄)创建 VMO 子项, 但有了此 RFC,便有可能实现 这有点像凭空提供新功能。
在这种情况下,风险没那么大
因为最终结果与创建新的 VMO 相同,并将数据复制到
(但内存用量更少),这在以前是可以实现的。
如果需要禁止此项操作
此 RFC 提议了 zx_vm_options_t
标志 (ZX_VM_CANNOT_CREATE_VMO_CHILD
)
可用。
测试
系统将对系统调用进行单元测试。 针对未来地址空间克隆实现的测试 也将用作系统调用的集成测试。
文档
此 RFC 是 zx_vmar_create_vmo_child
文档的基础。
缺点、替代方案和未知问题
哪些其他策略有可能解决同样的问题?
我们可以添加一个系统调用来执行整个地址空间克隆操作。 在接口和实现方面,这将是一个非常复杂的系统调用。 最好将复杂性引入用户空间。
我们可以添加一个系统调用,用于允许从映射中创建一个 VMO 句柄。
这样便可实现本质上是 zx_vmar_create_vmo_child
的用户空间实现,
首先根据映射创建一个句柄,然后调用 zx_vmo_create_child
。
但是,Zircon API 通常仅允许新建对象的创建句柄,
以使界面更易于推断。
此系统调用必须凭空创建句柄。
有很多技巧可以用来避免关闭任何 VMO 句柄,
例如,修改用于创建和映射 VMO 的所有代码以避免关闭它们;
或拦截 zx_handle_close
。
但是,这不足以实现地址空间克隆,
由于加载器服务会在开始运行之前将一些 VMO 映射到进程中,
这样并不能帮您处理这些事务
我们可以修改加载器服务,将必要的句柄传递给进程,
但这比添加此系统调用更复杂。
先验技术和参考资料
https://chromium.googlesource.com/chromium/src/+/master/docs/linux/zygote.md http://neugierig.org/software/chromium/notes/2011/08/zygote.html