摘要
在 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) 保留的页面执行缓存和内存操作。
offset 字节偏移量,用于指定 op 在 VMO 的保留内存中的起始位置。
要对其执行操作的 size 长度(以字节为单位)。
op 要执行的操作:
buffer 和 buffer_size 可能是必需的,也可能不使用,具体取决于下文所述的 op。
ZX_VMO_OP_COMMIT
- 提交大小为 VMO 的 size 字节(从字节 offset 开始)页面。
如需了解详情,请参阅 vm 对象文档。
需要右侧 ZX_RIGHT_WRITE
。
ZX_VMO_OP_DECOMMIT
- 释放之前提交到 VMO 的一系列页面(从 offset 到 offset+size),这会将该范围的字节重置为 0。需要右侧 ZX_RIGHT_WRITE
。
只有通过 zx_vmo_create()
创建的 vmos 没有非 Slice 子级,以及此类 vmos 的 Slice 子级,才支持此功能。提供的范围必须与页面对齐。
ZX_VMO_OP_ZERO
- 将 VMO 中的字节范围从 offset 重置为 offset+size 重置为 0。这在语义上等同于使用 zx_vmo_write()
写入 0,只不过它可以通过对共享的零页面进行去重处理来更高效地完成操作并节省内存。需要右侧 ZX_RIGHT_WRITE
。
ZX_VMO_OP_LOCK
- 锁定使用 ZX_VMO_DISCARDABLE
创建的 VMO 中的一系列页面,防止内核舍弃这些页面。保证会成功锁定 VMO,并在参数有效的情况下返回 ZX_OK
。buffer 应指向一个 zx_vmo_lock_state_t
结构体,buffer_size 应可容纳该结构体。返回 buffer 中已锁定和之前舍弃的范围的相关信息,以便客户端可以根据需要重新初始化已舍弃的内容。
整个 VMO 应该一次性锁定,因此 offset 应为 0,size 应为 VMO 的当前大小(zx_vmo_get_size()
将返回的页面对齐大小)。需要右侧 ZX_RIGHT_READ
或 ZX_RIGHT_WRITE
。请注意,锁定本身不会提交 VMO 中的任何页面;它只是将 VMO 的状态标记为“无法舍弃”。
buffer 应为 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_READ
或 ZX_RIGHT_WRITE
。请注意,锁定本身不会提交 VMO 中的任何页面;它只是将 VMO 的状态标记为“无法舍弃”。
ZX_VMO_OP_UNLOCK
- 在使用 ZX_VMO_DISCARDABLE
创建的 VMO 中解锁一系列页面,表示内核在内存紧张时可以自由舍弃这些页面。尚未舍弃的已解锁页面将计为已提交的页面。
整个 VMO 应该一次性解锁,因此 offset 应为 0,size 应为 VMO 的当前大小(zx_vmo_get_size()
将返回的页面对齐大小)。需要右侧 ZX_RIGHT_READ
或 ZX_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,效果微乎其微。
这仅适用于给定范围内已提交的页面,即不会因此操作提交任何新页面。如果需要,offset 将向下舍入为上一页面边界,而 offset+size 将向上舍入到下一个页面边界。
ZX_VMO_OP_ALWAYS_NEED
- 用于提示指定范围内的页面非常重要,应防止内存回收。当系统内存压力极大时,内核可能会决定替换此提示。此外,此提示也不会通过内存回收以外的其他方式(例如,取消提交、VMO 调整大小或 VMO 销毁)阻止页面被释放。旨在与使用 zx_pager_create_vmo()
创建的 VMO 搭配使用;对于其他 VMO 则没有太大影响。
在适用的情况下,这可以提交给定范围内的页面,例如,如果 VMO 由分页器直接提供支持,则将提交其页面;如果是克隆,则将提交父项中对此克隆可见的页面。如果需要,offset 将向上舍入到上一页面边界,而 offset+size 将向上舍入到下一页面边界。
请注意,ZX_VMO_OP_DONT_NEED
不会撤消之前的 ZX_VMO_OP_ALWAYS_NEED
。ZX_VMO_OP_ALWAYS_NEED
提示一直有效,直到内核因内存压力而决定替换提示为止。
权限
如果 op 为 ZX_VMO_OP_COMMIT
,则 handle 的类型必须为 ZX_OBJ_TYPE_VMO
且具有 ZX_RIGHT_WRITE
。
如果 op 为 ZX_VMO_OP_DECOMMIT
,则 handle 的类型必须为 ZX_OBJ_TYPE_VMO
且具有 ZX_RIGHT_WRITE
。
如果 op 为 ZX_VMO_OP_CACHE_SYNC
,则 handle 的类型必须为 ZX_OBJ_TYPE_VMO
且具有 ZX_RIGHT_READ
。
如果 op 为 ZX_VMO_OP_CACHE_INVALIDATE
,则 handle 的类型必须为 ZX_OBJ_TYPE_VMO
且具有 ZX_RIGHT_WRITE
。
如果 op 为 ZX_VMO_OP_CACHE_CLEAN
,则 handle 的类型必须为 ZX_OBJ_TYPE_VMO
且具有 ZX_RIGHT_READ
。
如果 op 为 ZX_VMO_OP_CACHE_CLEAN_INVALIDATE
,则 handle 的类型必须为 ZX_OBJ_TYPE_VMO
且具有 ZX_RIGHT_READ
。
返回值
zx_vmo_op_range()
会在成功时返回 ZX_OK
。如果失败,则返回负的错误值。
错误
ZX_ERR_BAD_HANDLE
句柄不是有效的句柄。
ZX_ERR_OUT_OF_RANGE
由 offset 和 size 指定的内存范围无效。
ZX_ERR_NO_MEMORY
向 ZX_VMO_OP_COMMIT
或 ZX_VMO_OP_ZERO
的提交页面分配失败。
ZX_ERR_WRONG_TYPE
句柄不是 VMO 句柄。
ZX_ERR_ACCESS_DENIED
标识名没有足够的权限来执行此操作。
ZX_ERR_INVALID_ARGS
是无效的指针(如果操作需要),op 不是有效的操作,size 为零且 op 是缓存操作,或者 op 是 ZX_VMO_OP_DECOMMIT
且范围未对齐页面。
在以下任意条件下,ZX_ERR_NOT_SUPPORTED
:
- op 为 ZX_VMO_OP_LOCK
、ZX_VMO_OP_TRY_LOCK
或 ZX_VMO_OP_UNLOCK
,并且未使用 ZX_VMO_DISCARDABLE
创建 VMO。
- op 为 ZX_VMO_OP_DECOMMIT
,底层 VMO 不允许取消提交。
- op 为 ZX_VMO_OP_CACHE_INVALIDATE
,kernel.enable-debugging-syscalls
为 false。
ZX_ERR_UNAVAILABLE
op 为 ZX_VMO_OP_TRY_LOCK
,VMO 可舍弃,该 VMO 已被内核舍弃。
ZX_ERR_BAD_STATE
op 为 ZX_VMO_OP_COMMIT
,则 VMO 由分页器提供支持,并且该分页器或 VMO 处于错误状态,导致无法填充所请求的页面。op 为 ZX_VMO_OP_UNLOCK
,VMO 可舍弃,并且 VMO 之前未被锁定。
ZX_ERR_IO
op 为 ZX_VMO_OP_COMMIT
,则 VMO 由分页器提供支持,并且分页器在提交所请求的页面时遇到了 I/O 错误。
ZX_ERR_IO_DATA_INTEGRITY
op 为 ZX_VMO_OP_COMMIT
,则 VMO 由分页器提供支持,并且分页器为所提交的页面读取的内容已损坏。
另请参阅
zx_vmo_create()
zx_vmo_create_child()
zx_vmo_get_size()
zx_vmo_read()
zx_vmo_set_size()
zx_vmo_write()