使用 process_vm_readv 读取任意数量的内存

使用 process_vm_readv 读取任意数量的内存

对于 process_vm_readv,linux 手册页指出:

[...](避免)在单个远程 iovec 元素中跨越内存页面(通常为 4KiB)。 (相反,将远程读取拆分为两个remote_iov元素,然后将它们合并回单个写入local_iov条目。第一个读取条目向上到达页边界,而第二个读取条目从下一页边界开始。)

我明白为什么这是一件事,但我不太明白应该如何解决它。我是否需要找出页面边界在哪里?或者只要我提供 2 个remote_iov 元素,该函数就会自行解决这个问题吗?如果我读取的内容超过 4kiB 并且可能跨越 2 个页面边界,我是否需要将远程元素分成 3 部分?

答案1

您应该真正阅读整个段落——这种分割 iovec 的方式并不是硬性要求。这只是应该在部分阅读的情况下提供帮助,尽管尚不清楚它如何提供帮助;-)

该联机帮助页相当可疑且令人困惑;我的测试表明,如果列表中的第一个 iovec不是有效地址,则process_vm_readv()总是会出错,但如果 iovec 跨越的任何页面或其余 iovec 未映射(这是预期的并且有用,但与下面强调的部分相矛盾)。iov_startremote_ioviov_start + iov_len

但请注意,这些系统调用不会检查远程进程中的内存区域直到执行读/写操作之前。因此,一个部分读/写(请参阅返回值)如果元素之一 remote_iov 指向远程进程中的无效内存区域,则可能会出现这种情况。超过该点将不会尝试进一步的读/写。当尝试从远程进程读取未知长度的数据(例如以 null 结尾的 C 字符串)时,请记住这一点,避免跨越单个远程 iovec 元素中的内存页(通常为 4KiB)。 (相反,将远程读取拆分为两个 remote_iov 元素,然后将它们合并回单个写入 local_iov条目。第一个读取条目向上到达页边界,而第二个读取条目从下一页边界开始。)

[...]

如果发生部分读/写,则此返回值可能小于请求的字节总数。 (部分转让适用于 iovec 元素的粒度。这些系统调用不会执行分割单个 iovec 元素的部分传输.)

相关内容