#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():
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 構造体の配列へのポイン タである。 iovec 構造体は <sys/uio.h> で以下のように定義 されている:
struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */
};
バッファーは配列の順序で処理される。 つまり、 process_vm_readv() は local_iov[0] が一杯になるまでデータを詰めてから、 local_iov[1] に進むことを意味する。 同様に、 remote_iov[0] を全部読み出してから remote_iov[1] に進み、 以降も同様である。
同様に、 process_vm_writev() は local_iov[0] の内容を全部読み出してから local_iov[1] に進み、 書き込み先でも remote_iov[0] が一杯になってから remote_iov[1] に進む。
長さ remote_iov[i].iov_len と local_iov[i].iov_len は同じである必要はない。 したがって、 ローカル側で 1 つのバッファーのデータがリモート側で複数のバッファーに分割されることがあるし、 その逆も起こりえる。
flags 引数は現在使用されておらず、 0 を設定しなければならない。
liovcnt と riovcnt で指定される値は IOV_MAX 以下でなければならない (IOV_MAX は <limits.h> で定義されており、 sysconf(_SC_IOV_MAX) の呼び出しでも入手できる)。
要素数引数と local_iov のチェックは、 すべてのデータ転送に先立って行われる。 要素数が大きすぎる場合や local_iov が無効な場合、 アドレスがローカルプロセスがアクセスできない領域を参照している場合は、 配列のどの要素も処理されず、 すぐにエラーが返される。
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 (see RETURN VALUE) may result if one of the remote_iov elements points to an invalid memory region in the remote process. No further reads/writes will be attempted beyond that point. Keep this in mind when attempting to read data of unknown length (such as C strings that are null-terminated) from a remote process, by avoiding spanning memory pages (typically 4 KiB) in a single remote iovec element. (Instead, split the remote read into two remote_iov elements and have them merge back into a single write local_iov entry. The first read entry goes up to the page boundary, while the second starts on the next page boundary.)
Permission to read from or write to another process is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check; see ptrace(2).
エラーの場合は -1 が返され、 errno が適切に設定される。
これらのシステムコールは、 (共有メモリーやパイプなどを使った場合に必要となる 2 回のコピーではなく) 1 回のコピー処理でメッセージの交換を許すことで、 高速なメッセージ送信をできるようにするために設計された。
#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;
}