摘要
对 VMO 拥有的分页器范围执行操作。
声明
#include <zircon/syscalls.h>
zx_status_t zx_pager_op_range(zx_handle_t pager,
uint32_t op,
zx_handle_t pager_vmo,
uint64_t offset,
uint64_t length,
uint64_t data);
说明
对范围 [offset, offset +
length) 中的 pager_vmo 执行由 op 指定的分页器操作。必须先通过
zx_pager_create_vmo()从pager创建pager_vmo。offset 和 length 必须与页面对齐。如果指定的 op 支持,则 data 是可选参数。
可以执行的操作,即 op 可以采用的值:
ZX_PAGER_OP_DIRTY - 用户空间分页器希望将范围 [offset,
offset + length) 中的页面从干净状态转换为脏状态。这将取消阻止任何等待指定范围的 ZX_PAGER_VMO_DIRTY 页面请求的写入。
ZX_PAGER_OP_FAIL - 用户空间分页器无法使用命令 ZX_PAGER_VMO_READ 或 ZX_PAGER_VMO_DIRTY 满足范围 [offset, offset + length) 中 pager_vmo 的页面请求。
data 包含遇到的错误(一个 zx_status_t 错误代码,符号扩展为 uint64_t
值)- 允许的值为 ZX_ERR_IO、ZX_ERR_IO_DATA_INTEGRITY、ZX_ERR_BAD_STATE、
ZX_ERR_NO_SPACE 和 ZX_ERR_BUFFER_TOO_SMALL。
这将向可能正在等待该范围内的页面请求的线程发出信号,从而取消阻止这些线程。如果被阻止的线程通过 zx_vmo_read() / zx_vmo_write() 或 zx_vmo_op_range()(使用 ZX_VMO_OP_COMMIT)请求页面,则调用将失败,并且系统会返回错误状态 (data)。如果被阻止的线程通过 VMAR 映射请求页面,则该线程将出现致命的页面错误异常。
ZX_PAGER_OP_WRITEBACK_BEGIN - 用户空间分页器希望开始写回范围
[offset, offset + length) 中的页面。这表示在写回完成后(以 ZX_PAGER_OP_WRITEBACK_END 为信号),有意清理指定范围内的任何脏页面。如需建议的用法,请参阅下面的示例代码。
您可以选择将 data 设置为 ZX_VMO_DIRTY_RANGE_IS_ZERO,以表明调用方希望将指定范围写回为零。当调用方处理
由 zx_pager_query_dirty_ranges() 返回的范围时,其 options 设置为
ZX_VMO_DIRTY_RANGE_IS_ZERO,则应使用此值。它可确保在查询后但在写回开始之前在该范围内创建的任何非零内容不会丢失,因为系统不会错误地假定其仍为零并将其标记为干净(因此可逐出)。
ZX_PAGER_OP_WRITEBACK_END - 用户空间分页器已完成写回范围
[offset, offset + length) 中的页面。这表示之前以 ZX_PAGER_OP_WRITEBACK_BEGIN 为信号的指定范围内的任何脏页面都可以标记为干净。如需建议的用法,请参阅下面的示例代码。
内核可以随意逐出任何已标记为干净的页面或零范围,之后,如果需要,用户空间分页器应再次提供这些页面或零范围。这也意味着分页器应注意不要有任何过时的供应正在进行中,并且应仅提供刚刚写回的新内容。
用于发现和清理任何脏页面的示例代码(取模错误处理)可能如下所示。
zx_vmo_dirty_range_t ranges[kMaxRanges];
uint64_t num_ranges;
zx_status_t st =
zx_pager_query_dirty_ranges(pager, vmo, 0, vmo_size, &ranges[0],
kMaxRanges * sizeof(zx_vmo_dirty_range_t), &num_ranges, nullptr);
for (uint64_t i = 0; i < num_ranges; i++) {
uint64_t start = ranges[i].offset;
uint64_t len = ranges[i].length;
st = zx_pager_op_range(pager, ZX_PAGER_OP_WRITEBACK_BEGIN, vmo, start, len, 0);
WritebackToDisk(vmo, start, len);
st = zx_pager_op_range(pager, ZX_PAGER_OP_WRITEBACK_END, vmo, start, len, 0);
}
权限
pager 必须是 ZX_OBJ_TYPE_PAGER 类型,并且具有 ZX_RIGHT_MANAGE_VMO。
pager_vmo 必须是 ZX_OBJ_TYPE_VMO 类型,并且具有 ZX_RIGHT_WRITE。
返回值
成功时,zx_pager_op_range() 会返回 ZX_OK;失败时,则会返回以下错误代码之一。
错误
ZX_ERR_BAD_HANDLE pager 或 pager_vmo 不是有效的句柄。
ZX_ERR_WRONG_TYPE pager 不是分页器句柄,或者 pager_vmo 不是 VMO 句柄。
ZX_ERR_ACCESS_DENIED pager 没有 ZX_RIGHT_MANAGE_VMO,或者 pager_vmo 没有
ZX_RIGHT_WRITE。
在以下任何情况下,ZX_ERR_INVALID_ARGS:
- pager_vmo 不是通过 pager 创建的 VMO。
- offset 或 length 未与页面对齐。
- op 是
ZX_PAGER_OP_FAIL,并且 data 不是ZX_ERR_IO、ZX_ERR_IO_DATA_INTEGRITY或ZX_ERR_BAD_STATE之一。 - op 是
ZX_PAGER_OP_WRITEBACK_BEGIN,并且 data 不是 0 或ZX_VMO_DIRTY_RANGE_IS_ZERO。
ZX_ERR_OUT_OF_RANGE pager_vmo 中指定的范围无效。
ZX_ERR_NOT_SUPPORTED op 在 pager_vmo 中指定的范围内不受支持。
ZX_ERR_NOT_FOUND op 是 ZX_PAGER_OP_DIRTY,并且由 offset 和 length 表示的范围包含未提供的区域,或者之前已填充但后来被内核逐出的区域。
ZX_ERR_BAD_STATE op 是 ZX_PAGER_OP_DIRTY 或 ZX_PAGER_OP_FAIL,并且 pager_vmo 已从 pager 中
分离。