PROCESS_VM_READV - Linux手册页

时间:2019-08-20 17:59:08  来源:igfitidea点击:

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()相反-它将数据从本地进程传输到远程进程。除了传输方向之外,参数liovcntlocal_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;
}

另外参见

readv(2),writev(2)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/