Virtual Memory Address Region(虚拟内存地址区域)


英文原文快照


名称

vm_address_region —— 虚拟内存地址空间的连续区域

概要

虚拟内存地址区域(VMAR)表示虚拟地址空间的连续部分。

描述

内核和用户空间使用VMAR来表示地址空间的分配。

每个进程启动时都带有一个包含整个地址空间的VMAR(根VMAR)(请参阅process_create)。 每个VMAR可以在逻辑上划分为任意数量的非重叠部分,每个部分代表虚拟内存的一个映射或间隙的子VMAR。 使用vmar_allocate创建子VMAR,以及通过使用vmar_map创建虚拟内存映射。

VMAR具有允许映射权限的分层权限模型。 例如,根VMAR允许读取,写入和可执行映射。 可以创建仅允许读写映射的子VMAR,其中创建允许可执行映射的子项是非法的。

使用vmar_allocate创建VMAR时,其父VMAR会保留对它的引用,因此,即使关闭子VMAR的所有句柄,则子对象及其后代也将在地址空间中保持存活状态。 为了将子节点与地址空间断开连接,必须在子节点的句柄上调用vmar_destroy

默认情况下,地址空间的所有分配都是随机的,并在VMAR创建时,调用者可以选择使用哪种随机化算法。 默认的分配器尝试在VMAR的整个空间上分配,使用ZX_VM_COMPACT选项的备用分配器会试图在VMAR内保持分配尽量簇聚在一起,但也是在空间范围内的随机位置。 建议开发者使用默认的分配器。

VMAR可选地支持固定偏移映射模式(也称为特定映射),此模式可用于创建守卫(guard)页面或确保映射的相对位置。 每个VMAR都可能具有ZX_VM_CAN_MAP_SPECIFIC权限,无论其父VMAR是否具有该权限。

例子

  1. #include <zircon/syscalls.h>
  2. /* 将此VMO映射到给定的VMAR,并使用在它之前|before|字节和它之后的|after|字节作为未映射的守卫空间。 */
  3. zx_status_t map_with_guard(zx_handle_t vmar, size_t before, size_t after,
  4. zx_handle_t vmo, uint64_t vmo_offset,
  5. size_t mapping_len, uintptr_t* mapped_addr,
  6. zx_handle_t* wrapping_vmar) {
  7. /* 这里省略了相关的检查代码 */
  8. const size_t child_vmar_size = before + after + mapping_len;
  9. const zx_vm_option_t child_vmar_options = ZX_VM_CAN_MAP_READ |
  10. ZX_VM_CAN_MAP_WRITE |
  11. ZX_VM_CAN_MAP_SPECIFIC;
  12. const zx_vm_option_t mapping_options = ZX_VM_SPECIFIC |
  13. ZX_VM_PERM_READ |
  14. ZX_VM_PERM_WRITE;
  15. uintptr_t child_vmar_addr;
  16. zx_handle_t child_vmar;
  17. zx_status_t status = zx_vmar_allocate(vmar, child_vmar_options, 0,
  18. child_vmar_size,
  19. &child_vmar,
  20. &child_vmar_addr);
  21. if (status != ZX_OK) {
  22. return status;
  23. }
  24. status = zx_vmar_map(child_vmar, mapping_options, before, vmo, vmo_offset,
  25. mapping_len, mapped_addr);
  26. if (status != ZX_OK) {
  27. zx_vmar_destroy(child_vmar);
  28. zx_handle_close(child_vmar);
  29. return status;
  30. }
  31. *wrapping_vmar = child_vmar;
  32. return ZX_OK;
  33. }

另见

系统调用