虚拟内存地址区域

姓名

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

摘要

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

说明

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

每个进程都从单个 VMAR(根 VMAR)开始,该 VMAR 涵盖整个地址空间(请参阅 zx_process_create())。每个 VMAR 在逻辑上都可以划分为任意数量的不重叠部分,每个部分代表一个子 VMAR、虚拟内存映射或间隙。您可以使用 zx_vmar_allocate() 创建子级 VMAR。使用 zx_vmar_map() 创建虚拟机映射。

VMAR 针对允许的映射权限采用分层权限模型。例如,根 VMAR 允许进行读取、写入和可执行映射。可以创建一个仅允许读取和写入映射的子级 VMAR,在这种情况下,创建允许执行映射的子级是非法的。

使用 zx_vmar_allocate() 创建 VMAR 时,其父级 VMAR 会保留对它的引用。因此,如果子级 VMAR 的所有句柄都关闭,子级 VMAR 的子级及其后代在地址空间中将保持活跃状态。若要将子节点与地址空间断开连接,必须对子节点的句柄调用 zx_vmar_destroy()

默认情况下,所有地址空间分配都是随机分配的。在创建 VMAR 时,调用方可以选择使用哪种随机算法。默认分配器会尝试在 VMAR 的整个宽度上广泛分布分配。使用 ZX_VM_COMPACT 选择的替代分配器会尝试使分配在 VMAR 内相近,但会位于范围内的随机位置。建议使用默认分配器。

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

示例

#include <zircon/syscalls.h>

/* Map this VMO into the given VMAR, with |before| bytes of unmapped guard space
   before it and |after| bytes after it.  */
zx_status_t map_with_guard(zx_handle_t vmar, size_t before, size_t after,
                           zx_handle_t vmo, uint64_t vmo_offset,
                           size_t mapping_len, uintptr_t* mapped_addr,
                           zx_handle_t* wrapping_vmar) {

    /* wrap around check elided */
    const size_t child_vmar_size = before + after + mapping_len;
    const zx_vm_option_t child_vmar_options = ZX_VM_CAN_MAP_READ |
                                              ZX_VM_CAN_MAP_WRITE |
                                              ZX_VM_CAN_MAP_SPECIFIC;
    const zx_vm_option_t mapping_options = ZX_VM_SPECIFIC |
                                           ZX_VM_PERM_READ |
                                           ZX_VM_PERM_WRITE;

    uintptr_t child_vmar_addr;
    zx_handle_t child_vmar;
    zx_status_t status = zx_vmar_allocate(vmar, child_vmar_options, 0,
                                          child_vmar_size,
                                          &child_vmar,
                                          &child_vmar_addr);
    if (status != ZX_OK) {
        return status;
    }

    status = zx_vmar_map(child_vmar, mapping_options, before, vmo, vmo_offset,
                         mapping_len, mapped_addr);
    if (status != ZX_OK) {
        zx_vmar_destroy(child_vmar);
        zx_handle_close(child_vmar);
        return status;
    }

    *wrapping_vmar = child_vmar;
    return ZX_OK;
}

另请参阅

系统调用