总结
对分页器拥有的一系列 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_vmo 的 op 执行分页操作,指定范围为 [offset, offset + length)。pager_vmo 必须之前由 zx_pager_create_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
执行 [pager_vmo, pager_vmo + pager_vmo) 范围内的 pager_vmo 页面请求。
pager_vmodata 包含遇到的错误(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_COMMIT
的 zx_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
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 中指定的范围无效。
pager_vmo 中指定的范围不支持“ZX_ERR_NOT_SUPPORTED
”op。
ZX_ERR_NOT_FOUND
op 是 ZX_PAGER_OP_DIRTY
,由偏移和长度表示的范围包含未提供的区域,或者之前填充但后被内核逐出的区域。
ZX_ERR_BAD_STATE
op 为 ZX_PAGER_OP_DIRTY
或 ZX_PAGER_OP_FAIL
,并且 pager_vmo 已与 pager 分离。