zx_vmo_op_range

摘要

对 VMO 的某个范围执行操作。

声明

#include <zircon/syscalls.h>

zx_status_t zx_vmo_op_range(zx_handle_t handle,
                            uint32_t op,
                            uint64_t offset,
                            uint64_t size,
                            void* buffer,
                            size_t buffer_size);

说明

zx_vmo_op_range()虚拟内存对象 (VMO) 持有的页面执行缓存和内存操作。

偏移量:字节偏移量,用于指定 op 在 VMO 持有内存中的起始位置。

要执行操作的大小(以字节为单位)。

要执行的操作:op

bufferbuffer_size 可能需要或未使用,具体取决于 op,如下所述。

ZX_VMO_OP_COMMIT - 提交从字节 offset 开始的 size 字节的页面,用于 VMO。 如需了解详情,请参阅 vm 对象文档。 需要 ZX_RIGHT_WRITE 权限。

ZX_VMO_OP_DECOMMIT - 从 offsetoffset+size 释放之前提交给 VMO 的一系列页面,并将该范围的字节重置为 0。需要 ZX_RIGHT_WRITE 权限。 此功能仅适用于通过 zx_vmo_create() 创建的没有非切片子项的 VMOS,以及此类 VMOS 的切片子项。提供的范围必须与页面对齐。

ZX_VMO_OP_PREFETCH - 预提取从字节 offset 开始的 size 字节的页面(针对 VMO)。实际页面可能已提交,也可能未提交,但未来对该范围的读取应具有与将此操作替换为对该范围的读取类似的性能特征。需要 ZX_RIGHT_READ 权限。

ZX_VMO_OP_ZERO - 将 VMO 中从 offsetoffset+size 的字节范围重置为 0。这在语义上等同于使用 zx_vmo_write() 写入 0,但它能够通过重复数据删除到共享零页面来更高效地完成此操作并节省内存。需要 ZX_RIGHT_WRITE 权限。

ZX_VMO_OP_LOCK - 锁定使用 ZX_VMO_DISCARDABLE 创建的 VMO 中的一系列页面,防止它们被内核舍弃。如果实参有效,则保证成功锁定 VMO 并返回 ZX_OKbuffer 应指向 zx_vmo_lock_state_t 结构体,并且 buffer_size 应容纳该结构体。返回有关 buffer 中锁定和之前舍弃的范围的信息,以便客户端在需要时重新初始化舍弃的内容。

应一次性锁定整个 VMO,因此 offset 应为 0,size 应为 VMO 的当前大小(即 zx_vmo_get_size() 将返回的经过页面对齐的大小)。需要 ZX_RIGHT_READZX_RIGHT_WRITE 权限。请注意,锁定本身不会提交 VMO 中的任何页面;它只会将 VMO 的状态标记为内核“不可舍弃”。

缓冲区应为 zx_info_lock_state_t 类型的指针。

typedef struct zx_vmo_lock_state {
  // |offset| and |size| track the locked range, and will be set to the |offset|
  // and |size| arguments passed in if the ZX_VMO_OP_LOCK is successful.
  uint64_t offset;
  uint64_t size;
  // |discarded_offset| and |discarded_size| track the discarded range prior to
  // the lock operation. This is the maximal range within the locked range that
  // contains discarded pages; not all pages within this range might have been
  // discarded. Both |discarded_offset| and |discarded_size| will be set to 0 if
  // the range was not discarded.
  uint64_t discarded_offset;
  uint64_t discarded_size;
} zx_vmo_lock_state_t;

ZX_VMO_OP_TRY_LOCK - 锁定使用 ZX_VMO_DISCARDABLE 创建的 VMO 中的一系列页面,防止它们被内核舍弃。只有在内核尚未舍弃该范围的情况下才会成功,否则会失败并显示 ZX_ERR_UNAVAILABLE。此操作旨在作为 ZX_VMO_OP_LOCK 的轻量级替代方案,用于尝试锁定 VMO,而无需设置 buffer 实参。此外,如果无法锁定 VMO,客户还可以选择不采取任何措施;如果客户希望再次锁定 VMO,则必须使用 ZX_VMO_OP_LOCK

应一次性锁定整个 VMO,因此 offset 应为 0,size 应为 VMO 的当前大小(即 zx_vmo_get_size() 将返回的经过页面对齐的大小)。需要 ZX_RIGHT_READZX_RIGHT_WRITE 权限。请注意,锁定本身不会提交 VMO 中的任何页面;它只是通过内核将 VMO 的状态标记为“不可舍弃”。

ZX_VMO_OP_UNLOCK - 解锁使用 ZX_VMO_DISCARDABLE 创建的 VMO 中的一系列页面,表示内核可以在内存压力下随意舍弃这些页面。尚未舍弃的已解锁页面将被视为已提交的页面。

整个 VMO 应一次性解锁,因此 offset 应为 0,size 应为 VMO 的当前大小(即 zx_vmo_get_size() 将返回的经过页面对齐的大小)。需要 ZX_RIGHT_READZX_RIGHT_WRITE 权限。

ZX_VMO_OP_CACHE_SYNC - 将指令缓存与数据缓存同步,以便指令提取能够看到之前的写入操作。 需要 ZX_RIGHT_READ 权限。

ZX_VMO_OP_CACHE_INVALIDATE - 执行缓存失效操作,以便未来的读取操作能够看到对主内存的外部更改。请注意,此操作仅在 kernel.enable-debugging-syscalls 为 true 时可用。如果未启用调试系统调用,此操作将失败并显示 ZX_ERR_NOT_SUPPORTED 错误。需要 ZX_RIGHT_WRITE 权限。

ZX_VMO_OP_CACHE_CLEAN - 清理(写回)数据缓存,以便在主内存中看到之前的写入。 需要 ZX_RIGHT_READ 权限。

ZX_VMO_OP_CACHE_CLEAN_INVALIDATE - 同时执行缓存清理和失效操作。 需要 ZX_RIGHT_READ 权限。

ZX_VMO_OP_DONT_NEED - 提示指定范围内的页面不再需要,应考虑回收内存。旨在与使用 zx_pager_create_vmo() 创建的 VMO 搭配使用;对于其他 VMO,会轻松成功。

这仅适用于指定范围内的已提交页面,也就是说,此操作不会提交任何新页面。如果需要,偏移量将向下舍入到上一个页面边界,偏移量+大小将向上舍入到下一个页面边界。

ZX_VMO_OP_ALWAYS_NEED - 指示指定范围内的页面很重要,应防止内存回收。当系统面临极大的内存压力时,内核可能会决定覆盖此提示。此提示也不会阻止通过内存回收以外的方式(例如取消提交、VMO 调整大小或 VMO 销毁)释放页面。旨在与使用 zx_pager_create_vmo() 创建的 VMO 搭配使用;对于其他 VMO,会顺利完成。

这可能会提交给定范围内的页面(如果适用),例如,如果 VMO 直接由分页程序支持,则其页面将被提交;或者,如果是克隆,则克隆可见的父级中的页面将被提交。如果需要,偏移量将向下舍入到上一个页面边界,而偏移量+大小将向上舍入到下一个页面边界。

请注意,ZX_VMO_OP_DONT_NEED 不会撤消之前的 ZX_VMO_OP_ALWAYS_NEEDZX_VMO_OP_ALWAYS_NEED 提示是粘性的,直到内核因内存压力而决定替换该提示为止。

权限

如果 opZX_VMO_OP_COMMIT,则 handle 必须为 ZX_OBJ_TYPE_VMO 类型,且具有 ZX_RIGHT_WRITE

如果 opZX_VMO_OP_DECOMMIT,则 handle 必须为 ZX_OBJ_TYPE_VMO 类型,且具有 ZX_RIGHT_WRITE

如果 opZX_VMO_OP_PREFETCH,则 handle 必须为 ZX_OBJ_TYPE_VMO 类型,且具有 ZX_RIGHT_READ

如果 opZX_VMO_OP_CACHE_SYNC,则 handle 必须为 ZX_OBJ_TYPE_VMO 类型,且具有 ZX_RIGHT_READ

如果 opZX_VMO_OP_CACHE_INVALIDATE,则 handle 必须为 ZX_OBJ_TYPE_VMO 类型,且具有 ZX_RIGHT_WRITE

如果 opZX_VMO_OP_CACHE_CLEAN,则 handle 必须为 ZX_OBJ_TYPE_VMO 类型,且具有 ZX_RIGHT_READ

如果 opZX_VMO_OP_CACHE_CLEAN_INVALIDATE,则 handle 必须为 ZX_OBJ_TYPE_VMO 类型,且具有 ZX_RIGHT_READ

返回值

如果成功,zx_vmo_op_range() 会返回 ZX_OK。如果失败,则返回负错误值。

错误

ZX_ERR_BAD_HANDLE handle 不是有效的 handle。

ZX_ERR_OUT_OF_RANGEoffsetsize 指定的无效内存范围。

ZX_ERR_NO_MEMORYZX_VMO_OP_COMMITZX_VMO_OP_PREFETCHZX_VMO_OP_ZERO 分配提交页面失败。

ZX_ERR_WRONG_TYPE handle 不是 VMO handle。

ZX_ERR_ACCESS_DENIED 句柄没有足够的权限来执行该操作。

ZX_ERR_INVALID_ARGS buffer 是无效指针(如果操作需要),op 不是有效操作,size 为零且 op 是缓存操作,或者 opZX_VMO_OP_DECOMMIT 且范围未与页面对齐。

在以下任何情况下,请选择 ZX_ERR_NOT_SUPPORTED

  • opZX_VMO_OP_LOCKZX_VMO_OP_TRY_LOCKZX_VMO_OP_UNLOCK,且 VMO 不是使用 ZX_VMO_DISCARDABLE 创建的。
  • opZX_VMO_OP_DECOMMIT,但底层 VMO 不允许取消提交。
  • opZX_VMO_OP_CACHE_INVALIDATE,且 kernel.enable-debugging-syscalls 为 false。
  • opZX_VMO_OP_CACHE_SYNCZX_VMO_OP_CACHE_INVALIDATEZX_VMO_OP_CACHE_CLEANZX_VMO_OP_CACHE_CLEAN_INVALIDATE,并且 VMO 是使用 zx_vmo_create_physical() 创建的或从 zx_vmo_create_physical() 派生的

ZX_ERR_UNAVAILABLE opZX_VMO_OP_TRY_LOCK,VMO 可丢弃,并且已被内核丢弃。

ZX_ERR_BAD_STATE opZX_VMO_OP_COMMITZX_VMO_OP_PREFETCH,VMO 由分页器提供支持,并且分页器或 VMO 处于不良状态,导致无法填充所请求的页面。opZX_VMO_OP_UNLOCK,VMO 可舍弃,并且之前未锁定。

ZX_ERR_IO opZX_VMO_OP_COMMITZX_VMO_OP_PREFETCH,VMO 由分页器提供支持,并且分页器在提交所请求的页面时遇到 I/O 错误。

ZX_ERR_IO_DATA_INTEGRITY opZX_VMO_OP_COMMITZX_VMO_OP_PREFETCH,则 VMO 由分页器支持,并且分页器为正在提交的页面读入的内容已损坏。

另请参阅