摘要
添加内存映射。
声明
#include <zircon/syscalls.h>
zx_status_t zx_vmar_map(zx_handle_t handle,
zx_vm_option_t options,
size_t vmar_offset,
zx_handle_t vmo,
uint64_t vmo_offset,
size_t len,
zx_vaddr_t* mapped_addr);
说明
将给定 VMO 映射到给定的虚拟内存地址区域。映射会保留对底层虚拟内存对象的引用,这意味着关闭 VMO 句柄不会移除此函数添加的映射。
options 是以下各项的位矢量:
ZX_VM_SPECIFIC
使用 vmar_offset 放置映射;如果 handle 没有ZX_VM_CAN_MAP_SPECIFIC
权限,则无效。vmar_offset 是相对于给定 VMAR 的基地址的偏移量。如果指定的范围与其他 VMAR 或映射重叠,则会出错。ZX_VM_SPECIFIC_OVERWRITE
与ZX_VM_SPECIFIC
相同,但可以与其他映射重叠。与其他 VMAR 部分重叠仍会导致错误。如果范围符合这些要求,则会以原子方式(相对于所有其他映射/取消映射/保护操作)替换 vmar_offset 和 len 指定的范围内的现有映射。如果该范围与任何映射部分重叠,则这些映射在该范围之外的部分仍会保持映射状态。ZX_VM_OFFSET_IS_UPPER_LIMIT
将 vmar_offset 解释为上限,以限制内核选择偏移量;如果 handle 没有ZX_VM_CAN_MAP_SPECIFIC
权限,则无效。生成的映射将具有 offset + len,且该值小于等于 vmar_base + vmar_offset。如果使用ZX_VM_SPECIFIC
或ZX_VM_SPECIFIC_OVERWRITE
,则无法指定此选项。ZX_VM_PERM_READ
将 vmo 映射为可读。如果 handle 没有ZX_VM_CAN_MAP_READ
权限、handle 没有ZX_RIGHT_READ
权限,或者 vmo handle 没有ZX_RIGHT_READ
权限,则会出错。ZX_VM_PERM_WRITE
将 vmo 映射为可写入。如果 handle 没有ZX_VM_CAN_MAP_WRITE
权限、handle 没有ZX_RIGHT_WRITE
权限、vmo handle 没有ZX_RIGHT_WRITE
权限,或者 options 未指定ZX_VM_PERM_READ
,则会出错。ZX_VM_PERM_EXECUTE
将 vmo 映射为可执行文件。如果 handle 没有ZX_VM_CAN_MAP_EXECUTE
权限、handle 句柄没有ZX_RIGHT_EXECUTE
权限、vmo 句柄没有ZX_RIGHT_EXECUTE
权限,或者 options 未指定ZX_VM_PERM_READ
,则会出错。ZX_VM_MAP_RANGE
将 VMO 的所有后备区域立即分页到新映射中。如果使用ZX_VM_SPECIFIC_OVERWRITE
,则无法指定此属性。ZX_VM_ALLOW_FAULTS
如果创建的映射可能会生成故障,则必须提供。特别要指出的是,如果 vmo 可调整大小、vmo 不可调整大小但映射超出 vmo 的末尾、vmo 可丢弃,或者 vmo 是通过zx_pager_create_vmo()
创建的,则必须使用该函数。ZX_VM_PERM_READ_IF_XOM_UNSUPPORTED
如果系统不支持映射仅限执行的页面,则将 vmo 映射为可读。如果系统可以映射只执行映像,则会忽略此标志。ZX_VM_REQUIRE_NON_RESIZABLE
如果 vmo 可调整大小,则失败。
如果 options 未设置 ZX_VM_SPECIFIC
、ZX_VM_SPECIFIC_OVERWRITE
或 ZX_VM_OFFSET_IS_UPPER_LIMIT
,则 vmar_offset 必须为 0。ZX_VM_OFFSET_IS_UPPER_LIMIT
用于约束选择范围,否则其行为与未设置 ZX_VM_SPECIFIC
和 ZX_VM_SPECIFIC_OVERWRITE
的情况类似,即内核会随机为映射分配偏移量(分配器由目标 VMAR 上设置的政策决定)。
len 必须为非零值且与页面对齐。
此外,您还可以添加以下某个二进制幂对齐标志:
ZX_VM_ALIGN_1KB
会将 child_addr 对齐到至少 1K 字节的 2 的幂。ZX_VM_ALIGN_2KB
会将 child_addr 对齐到至少 2K 字节的 2 的幂。ZX_VM_ALIGN_4KB
会将 child_addr 对齐到至少 4K 字节的 2 的幂。ZX_VM_ALIGN_8KB
会将 child_addr 对齐到至少 8K 字节的 2 的幂,并继续对齐到ZX_VM_ALIGN_4GB
会将 child_addr 对齐到至少 4G 字节的 2 的幂。
如果 vmar 基地址 + vmo_offset 与请求的值不对齐,则将无法将 ZX_VM_ALIGN
标志与 ZX_VM_SPECIFIC
搭配使用。
权限
handle 必须为 ZX_OBJ_TYPE_VMAR
类型。
vmo 必须为 ZX_OBJ_TYPE_VMO
类型。
返回值
成功时,zx_vmar_map()
会返回 ZX_OK
和映射的绝对基地址(通过 mapped_addr)。基地址将与页面对齐且不为零。如果失败,则会返回负错误值。
错误
ZX_ERR_BAD_HANDLE
handle 或 vmo 不是有效的 handle。
ZX_ERR_WRONG_TYPE
handle 或 vmo 分别不是 VMAR 或 VMO 句柄。
ZX_ERR_BAD_STATE
handle 是指已销毁的 VMAR。
ZX_ERR_INVALID_ARGS
适用于以下任一情况:
- mapped_addr 或 options 无效。
- 如果未指定 ZX_VM_SPECIFIC
、ZX_VM_SPECIFIC_OVERWRITE
或 ZX_VM_OFFSET_IS_UPPER_LIMIT
,则 vmar_offset 不为零。
- 同时指定了 ZX_VM_SPECIFIC_OVERWRITE
和 ZX_VM_MAP_RANGE
。
- ZX_VM_OFFSET_IS_UPPER_LIMIT
与 ZX_VM_SPECIFIC
或 ZX_VM_SPECIFIC_OVERWRITE
一起指定。
- vmar_offset 和 len 描述了因超出区域边界而无法满足的分配。
- vmar_offset 或 vmo_offset 未对齐到页面。
- len 为 0 或未对齐到页面。
已指定 ZX_ERR_ALREADY_EXISTS
ZX_VM_SPECIFIC
,但未指定 ZX_VM_SPECIFIC_OVERWRITE
,并且请求的范围与其他映射重叠。
ZX_ERR_NO_RESOURCES
如果在 VMAR 中找不到用于创建映射的位置。
ZX_ERR_ACCESS_DENIED
权限不足,无法进行请求的映射。
ZX_ERR_NOT_SUPPORTED
如果 vmo 可调整大小、可丢弃或由页面器支持,但未设置 ZX_VM_ALLOW_FAULTS
。
ZX_ERR_NOT_SUPPORTED
如果 vmo 可调整大小且已设置 ZX_VM_REQUIRE_NON_RESIZABLE
。
ZX_ERR_BUFFER_TOO_SMALL
VMO 不可调整大小,并且映射超出了 VMO 的末尾,但未设置 ZX_VM_ALLOW_FAULTS
。
ZX_ERR_NO_MEMORY
因内存不足而失败。用户空间没有很好的方式来处理这种(不太可能发生的)错误。
在未来的 build 中,此错误将不再出现。
ZX_ERR_OUT_OF_RANGE
vmo_offset + ROUNDUP(len, PAGE_SIZE)
溢出。
备注
可将用于支持内存映射的 VMO 调整为较小的大小。这可能会导致线程读取或写入 VMAR 区域时发生故障。为避免此类风险,从客户端接收 VMO 的服务应在映射 VMO 时使用 ZX_VM_REQUIRE_NON_RESIZABLE
。