PROCESS_VM_READV - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
process_vm_readv,process_vm_writev-在进程地址空间之间传输数据
语法
#include <sys/uio.h> ssize_t process_vm_readv(pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags); ssize_t process_vm_writev(pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags);
glibc的功能测试宏要求(请参阅feature_test_macros(7)):
process_vm_readv(),process_vm_writev():
- _GNU_SOURCE
说明
这些系统调用在调用进程("本地进程")和pid标识的进程("远程进程")的地址空间之间传输数据。数据直接在两个进程的地址空间之间移动,而不经过内核空间。
process_vm_readv()系统调用将数据从远程进程传输到本地进程。待传输的数据由remote_iov和riovcnt标识:remote_iov是指向描述进程pid中地址范围的数组的指针,而riovcnt指定remote_iov中的元素数。数据将传输到由local_iov和liovcnt指定的位置:local_iov是指向描述调用过程中地址范围的数组的指针,而liovcnt指定local_iov中元素的数量。
process_vm_writev()系统调用与process_vm_readv()相反-它将数据从本地进程传输到远程进程。除了传输方向之外,参数liovcnt,local_iov,riovcnt和remote_iov具有与process_vm_readv()相同的含义。
local_iov和remote_iov参数指向iovec结构的数组,定义为:
struct iovec { void *iov_base; /* Starting address */ size_t iov_len; /* Number of bytes to transfer */ };
缓冲区以数组顺序处理。这意味着process_vm_readv()在继续进行到local_iov [1]之前会完全填充local_iov [0],依此类推。同样,在继续进行remote_iov [1]之前,将完全读取remote_iov [0],依此类推。
同样,process_vm_writev()在继续进行local_iov [1]之前写出local_iov [0]的全部内容,并在继续进行remote_iov [1]之前完全填充remote_iov [0]。
remote_iov [i] .iov_len和local_iov [i] .iov_len的长度不必相同。因此,可以将单个本地缓冲区拆分为多个远程缓冲区,反之亦然。
flags参数当前未使用,必须设置为0。
liovcnt和riovcnt参数中指定的值必须小于或等于IOV_MAX(在调用sysconf(_SC_IOV_MAX)中定义或可通过调用sysconf(_SC_IOV_MAX)访问)。
在执行任何传输之前,将检查count参数和local_iov。如果计数太大,或者local_iov无效,或者地址引用的是本地进程无法访问的区域,则不会处理任何向量,并且会立即返回错误。
但是请注意,这些系统调用在进行读/写操作之前不会检查远程进程中的内存区域。因此,如果remote_iov元素之一指向远程进程中的无效内存区域,则可能会导致部分读取/写入(请参见RETURN VALUE)。在此之后,将不再尝试进行进一步的读取/写入。在尝试从远程进程中读取未知长度的数据(例如以N结尾的C字符串)时,请避免在单个iovec远程元素中跨越内存页面(通常为4 KiB),请牢记这一点。 (相反,将远程读取分成两个remote_iov元素,然后将它们合并回到单个写入local_iov条目中。第一个读取条目到达页面边界,而第二个读取条目开始于下一个页面边界。)
读取或写入另一个进程的权限由ptrace访问模式PTRACE_MODE_ATTACH_REALCREDS检查控制;参见ptrace(2)。
返回值
成功后,process_vm_readv()返回读取的字节数,process_vm_writev()返回写入的字节数。如果发生部分读/写,则此返回值可能小于请求的字节总数。 (部分传输适用于iovec元素的粒度。这些系统调用不会执行拆分单个iovec元素的部分传输。)调用方应检查返回值以确定是否发生了部分读/写。
错误时,返回-1并正确设置errno。
错误说明
- EFAULT
- local_iov描述的内存在调用者的可访问地址空间之外。
- EFAULT
- remote_iov描述的内存在进程pid的可访问地址空间之外。
- EINVAL
- local_iov或remote_iov的iov_len值之和溢出了ssize_t值。
- EINVAL
- 标志不为0。
- EINVAL
- liovcnt或riovcnt太大。
- ENOMEM
- 无法为iovec结构的内部副本分配内存。
- EPERM
- 调用者无权访问进程pid的地址空间。
- ESRCH
- 不存在ID为pid的进程。
版本
这些系统调用是在Linux 3.2中添加的。从2.15版开始,glibc提供了支持。
遵循规范
这些系统调用是非标准的Linux扩展。
备注
不能以任何方式保证由process_vm_readv()和process_vm_writev()执行的数据传输是原子的。
这些系统调用旨在通过允许使用单拷贝操作(而不是使用例如共享内存或管道时需要的双拷贝)交换消息来允许快速传递消息。
示例
以下代码示例演示了process_vm_readv()的用法。它从具有PID 10的进程中读取地址0x10000处的20个字节,并将前10个字节写入buf1,将后10个字节写入buf2。
#include <sys/uio.h> int main(void) { struct iovec local[2]; struct iovec remote[1]; char buf1[10]; char buf2[10]; ssize_t nread; pid_t pid = 10; /* PID of remote process */ local[0].iov_base = buf1; local[0].iov_len = 10; local[1].iov_base = buf2; local[1].iov_len = 10; remote[0].iov_base = (void *) 0x10000; remote[0].iov_len = 20; nread = process_vm_readv(pid, local, 2, remote, 1, 0); if (nread != 20) return 1; else return 0; }
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。