process_vm_readv.2: Many additions, rewrites, and clarifications

Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
Michael Kerrisk 2012-03-20 10:03:55 +13:00
parent 9762bc8a64
commit 7985dbf3f7
1 changed files with 159 additions and 113 deletions

View File

@ -1,5 +1,6 @@
.\" Copyright (C) 2011 Christopher Yeoh <cyeoh@au1.ibm.com>
.\" Copyright (C) 2012 Mike Frysinger <vapier@gentoo.org>
.\" and Copyright (C) 2012 Mike Frysinger <vapier@gentoo.org>
.\" and Copyright (C) 2012 Michael Kerrisk <mtk.man-pages@gmail.com>
.\"
.\" Permission is granted to make and distribute verbatim copies of this
.\" manual provided the copyright notice and this permission notice are
@ -21,78 +22,83 @@
.\" Formatted or processed versions of this manual, if unaccompanied by
.\" the source, must acknowledge the copyright and authors of this work.
.\"
.TH PROCESS_VM_READV 2 2012-03-09 "Linux" "Linux Programmer's Manual"
.\" Commit fcf634098c00dd9cd247447368495f0b79be12d1
.\"
.TH PROCESS_VM_READV 2 2012-03-25 "Linux" "Linux Programmer's Manual"
.SH NAME
process_vm_readv, process_vm_writev \- read/write from/to another processes' address space
process_vm_readv, process_vm_writev \- transfer data between process address spaces
.SH SYNOPSIS
.B #include <sys/uio.h>
.sp
.nf
.BI "ssize_t process_vm_readv(pid_t " pid ,
.br
.BI " const struct iovec *" lvec ,
.br
.BI " const struct iovec *" local_iov ,
.BI " unsigned long " liovcnt ,
.br
.BI " const struct iovec *" rvec ,
.br
.BI " const struct iovec *" remote_iov ,
.BI " unsigned long " riovcnt ,
.br
.BI " unsigned long " flags ");"
.BI "ssize_t process_vm_writev(pid_t " pid ,
.br
.BI " const struct iovec *" lvec ,
.br
.BI " const struct iovec *" local_iov ,
.BI " unsigned long " liovcnt ,
.br
.BI " const struct iovec *" rvec ,
.br
.BI " const struct iovec *" remote_iov ,
.BI " unsigned long " riovcnt ,
.br
.BI " unsigned long " flags ");"
.fi
.SH DESCRIPTION
These system calls transfer data between the address space
of the calling process ("the local process") and the process identified by
.IR pid
("the remote process").
The data moves directly between the address spaces of the two processes,
without passing through kernel space.
The
.BR process_vm_readv ()
function reads from the memory locations described by the
.I riovcnt
buffers from
.I rvec
in the process identified by
system call transfers data from the process
.I pid
into
.I liovcnt
buffers described by
.I lvec
in the current process.
to the calling process.
The data to be transferred is identified by
.IR remote_vec
and
.IR riovcnt :
.IR remote_vec
is a pointer to an array describing address ranges in the process
.IR pid ,
and
.IR riovcnt
specifies the number of items in
.IR remote_vec .
The data is transferred to the locations specified by
.IR local_vec
and
.IR liovcnt :
.IR local_vec
is a pointer to an array describing address ranges in the calling process,
and
.IR liovcnt
specifies the specifies the number of items in
.IR local_vec .
The
.BR process_vm_writev ()
function is the inverse of
system call is the converse of
.BR process_vm_readv ()\(emit
writes into the memory locations described by
.I riovcnt
buffers
from
.I rvec
in the process identified by
.I pid
into
.I liovcnt
buffers described by
.I lvec
in the current process.
transfers data from the calling process to the process
.IR pid .
Other than the direction of the transfer, the arguments
.IR liovcnt ,
.IR local_vec ,
.IR liovcnt ,
and
.IR remote_vec
have the same meaning as for
.BR process_vm_readv ().
The count values might be individually capped according to
.BR UIO_MAXIOV .
If the Linux kernel is capped at smaller values, the C library will take care
of emulating the limit it exposes (if it is bigger) so the user only needs to
care about that (what the C library defines).
The pointers
.I lvec
The
.I local_iov
and
.I rvec
point to an array of
.I remote_iov
arguments point to an array of
.I iovec
structures, defined in
.IR <sys/uio.h>
@ -107,75 +113,102 @@ struct iovec {
.fi
.in
Buffers are processed in array order. This means that
Buffers are processed in array order.
This means that
.BR process_vm_readv ()
completely fills
.I lvec[0]
.I local_iov[0]
before proceeding to
.IR lvec[1] ,
and
so on.
Along those lines,
.I rvec[0]
.IR local_iov[1] ,
and so on.
Likewise,
.I remote_iov[0]
is completely read before proceeding to
.I rvec[1]
.IR remote_iov[1] ,
and so on.
Similarly,
.BR process_vm_writev ()
writes out the entire contents of
.I lvec[0]
.I local_iov[0]
before proceeding to
.IR lvec[1] ,
.IR local_iov[1] ,
and it completely fills
.I revc[0]
before proceeding
to
.IR rvec[1] .
.I remote_vec[0]
before proceeding to
.IR remote_iov[1] .
The lengths of
.I rvec[i]
.I remote_iov[i].iov_len
and
.I lvec[i]
.I local_iov[i].iov_len
do not have to be the same.
This allows you to split a single local buffer into multiple remote buffers,
or vice versa.
The data transfers of
.BR process_vm_readv ()
and
.BR process_vm_writev ()
are not guaranteed to be atomic in any way.
The counts and vectors are checked before doing any transfers. So if the
counts are too big, or the vectors invalid, or the addresses refer to regions
that are inaccessible, none of the previous vectors will be processed and an
error will be returned immediately. Keep this in mind when attempting to
extract data of unknown length (such as C strings which are NULL terminated)
by avoiding spanning memory pages (typically 4KiB).
Thus, it is possible to split a single local buffer
into multiple remote buffers, or vice versa.
The
.I flags
parameter is currently unused and must be set to 0.
argument is currently unused and must be set to 0.
In order to read or write from or to another process you must have
the capability
.BR CAP_SYS_PTRACE
or have the same uid and gid of the target process. The permission
required is exactly the same as being able to perform a
The values specified in the
.I liovcnt
and
.I riovcnt
arguments must be less than or equal to
.BR IOV_MAX
(defined in
.I <limits.h>
or accessible via the call
.IR sysconf(_SC_IOV_MAX) ).
.\" In time, glibc might provide a wrapper that works around this limit,
.\" as is done for readv()/writev()
The count arguments and
.IR local_vec
are checked before doing any transfers.
If the counts are too big, or
.I local_vec
is invalid,
or the addresses refer to regions that are inaccessible in the local process,
none of the vectors will be processed and an
error will be returned immediately.
.\" FIXME: What does the following sentence mean?
Keep this in mind when attempting to
extract data of unknown length (such as C strings which are null-terminated)
by avoiding spanning memory pages (typically 4KiB).
Note, however, that these system calls do not check the memory regions
in the remote process until just before doing the read/write.
Consequently, a partial read/write may result if one of the
.I remote_vec
elements points to an invalid memory region in the remote process.
No further reads/writes will be attempted beyond that point.
In order to read from or write to another process,
either the caller must have the capability
.BR CAP_SYS_PTRACE ,
or
the real, effective, and saved set user IDs
of the target process must match the real user ID of the caller
.I and
the real, effective, and saved set group IDs
of the target process must match the real group ID of the caller.
(The permission required is exactly the same as that required to perform a
.BR ptrace (2)
ptrace with
.BR PTRACE_ATTACH
on the target process.
on the target process.)
.SH "RETURN VALUE"
On success,
.BR process_vm_readv ()
returns the number of bytes read while
returns the number of bytes read and
.BR process_vm_writev ()
returns the number of bytes written.
(This return value may be less than the total number of requested bytes,
if a partial read/write occurred.
The caller should check the return value to determine whether
a partial read/write occurred.)
On error, the number of bytes read or written is returned, or -1 is
returned if it was unable to read/write any bytes; in either case,
On error, \-1 is returned and
.I errno
is set appropriately.
.SH ERRORS
@ -184,51 +217,64 @@ is set appropriately.
The sum of the
.I iov_len
values of either
.I lvec
.I local_iov
or
.I rvec
.I remote_iov
overflows a
.I ssize_t
value.
.TP
.B EINVAL
The value of the
.I flags
parameter is not 0.
is not 0.
.TP
.B EINVAL
.I liovcnt
or
.I riovcnt
is too large.
.TP
.B EFAULT
The memory described by
.I lvec
is outside your accessible address space.
.I local_iov
is outside the caller's accessible address space.
.TP
.B EFAULT
The memory described by
.I rvec
is outside the accessible address space
of process
.I remote_iov
is outside the accessible address space of the process
.IR pid .
.TP
.B ENOMEM
Out of memory.
.TP
.B EPERM
.RB ( process_vm_readv ())
You do not have permission to read from process
.IR pid .
.TP
.B EPERM
.RB ( process_vm_writev ())
You do not have permission to write to process
The caller does not have permission to access the address space of the process
.IR pid .
.TP
.B ESRCH
No process with ID
.I pid
does not exist.
exists.
.SH VERSIONS
These functions are available since glibc 2.15 and Linux 3.2.
These system calls were added in Linux 3.2.
Support is provided in glibc since version 2.15.
.SH "CONFORMING TO"
These functions are Linux extensions, not in C or POSIX.
These system calls are nonstandard Linux extensions.
.SH NOTES
The data transfers performed by
.BR process_vm_readv ()
and
.BR process_vm_writev ()
are not guaranteed to be atomic in any way.
These system calls were designed to permit fast message passing
by allowing messages to be exchanged with a single copy operation
(rather than the double copy that would be required
when using, for example, shared memory or pipes).
.\" Original user is MPI, http://www.mcs.anl.gov/research/projects/mpi/
.\" See also some benchmarks at http://lwn.net/Articles/405284/
.\" and http://marc.info/?l=linux-mm&m=130105930902915&w=2
.SH EXAMPLE
The following code sample demonstrates the use of
.BR process_vm_readv ().