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是否具有该权限。
例子
#include <zircon/syscalls.h>
/* 将此VMO映射到给定的VMAR,并使用在它之前|before|字节和它之后的|after|字节作为未映射的守卫空间。 */
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) {
/* 这里省略了相关的检查代码 */
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;
}
另见
- vm_object —— 虚拟内存对象
系统调用
- vmar_allocate —— 创建新的子VMAR
- vmar_map —— 将VMO映射到进程
- vmar_unmap —— 从进程中取消映射的内存区域
- vmar_protect —— 调整内存访问权限
- vmar_destroy —— 销毁VMAR及其所有子VMAR