zx_pager_op_range

总结

对分页器拥有的一系列 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);

说明

pager_vmoop 执行分页操作,指定范围为 [offset, offset + length)。pager_vmo 必须之前由 zx_pager_create_vmo() 通过分页器创建。offsetlength 必须与页面对齐。如果指定的 op 支持,则 data 是一个可选参数。

可执行的操作,即值 op 可采用:

ZX_PAGER_OP_DIRTY - 用户空间分页器想要将 [offset, offset +length) 范围内的页面从干净到脏页转换。这将取消屏蔽指定范围内正在等待 ZX_PAGER_VMO_DIRTY 页面请求的所有写入操作。

ZX_PAGER_OP_FAIL - 用户空间分页器未能使用命令 ZX_PAGER_VMO_READZX_PAGER_VMO_DIRTY 执行 [pager_vmo, pager_vmo + pager_vmo) 范围内的 pager_vmo 页面请求。 pager_vmodata 包含遇到的错误(zx_status_t 错误代码符号扩展为 uint64_t 值),允许的值包括 ZX_ERR_IOZX_ERR_IO_DATA_INTEGRITYZX_ERR_BAD_STATEZX_ERR_NO_SPACEZX_ERR_BUFFER_TOO_SMALL

这会向可能正在等待该范围内页面请求的线程发出信号,从而将其取消屏蔽。如果被屏蔽的线程之前通过 zx_vmo_read() / zx_vmo_write() 或包含 ZX_VMO_OP_COMMITzx_vmo_op_range() 来请求页面,则调用将失败并返回错误状态 (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 pagerpager_vmo 不是有效的句柄。

ZX_ERR_WRONG_TYPE pager 不是分页器句柄,或 pager_vmo 不是 VMO 句柄。

ZX_ERR_ACCESS_DENIED pager 没有 ZX_RIGHT_MANAGE_VMOpager_vmo 没有 ZX_RIGHT_WRITE

在以下任意条件下,ZX_ERR_INVALID_ARGS: - pager_vmo 不是通过 pager 创建的 VMO。 - offsetlength 不对齐页面。 - opZX_PAGER_OP_FAILdata 不是 ZX_ERR_IOZX_ERR_IO_DATA_INTEGRITYZX_ERR_BAD_STATE 其中之一。 - opZX_PAGER_OP_WRITEBACK_BEGINdata 不为 0 或 ZX_VMO_DIRTY_RANGE_IS_ZERO

ZX_ERR_OUT_OF_RANGEpager_vmo 中指定的范围无效。

pager_vmo 中指定的范围不支持“ZX_ERR_NOT_SUPPORTEDop

ZX_ERR_NOT_FOUND op 是 ZX_PAGER_OP_DIRTY,由偏移和长度表示的范围包含未提供的区域,或者之前填充但后被内核逐出的区域。

ZX_ERR_BAD_STATE opZX_PAGER_OP_DIRTYZX_PAGER_OP_FAIL,并且 pager_vmo 已与 pager 分离。

另请参阅