Provided by: manpages-ja-dev_0.5.0.0.20210215+dfsg-1_all
名前
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 で指定されるプ ロセス (「リモートプロセス」) のアドレス空間間でデータを転送する。 データの移動は、 カーネ ル空間を経由することなく、 2 つのプロセスのアドレス空間間で直接行われる。 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 が無効な場合、 アドレスがローカルプロセスがアクセスできない領域を 参照している場合は、 配列のどの要素も処理されず、 すぐにエラーが返される。 ただし、 これらのシステムコールは、 実際に読み出し/書き込みを行う直前までリモートプロセス のメモリー領域のチェックを行わない点に注意すること。 結果として、 remote_iov の要素の一つ がリモートプロセスで無効なメモリー領域を参照している場合、 部分的な読み出し/書き込み (「返 り値」の節を参照) が行われることになる。 これ以降は読み出し/書き込みは行われない。 リモー トプロセスから長さ不明のデータ (例えば NULL 終端された C 文字列) を読み出す際で、 リモート 側の一つの iovec 要素が複数のメモリーページ (通常は 4KiB) にまたがらないようにしている場合 は、 この点に注意が必要である。 (リモートからの読み出しを 2 つの remote_iov 要素に分割し、 1 つの local_iov 要素への書き込みにマージすればよい。 最初の読み出しでページ境界まで読み出 し、 次の読み出しを次のページ境界から行う。) 他のプロセスからの読み出しや他のプロセスへの書き込みを行うには、 呼び出し元がケーパビリ ティ CAP_SYS_PTRACE を持っていなければならない、もしくは、 リモートプロセスの実ユーザー ID、 実効ユーザー ID、 保存 set-user-ID が呼び出し元の実ユーザー ID と一致し、 かつリモー トプロセスの実グループ ID、 実効グループ ID、 保存 set-group-ID が呼び出し元の実グループ ID と一致していなければならない。 (ここで必要なアクセス許可は、 リモートプロセスに対して ptrace(2) の PTRACE_ATTACH を実行するのに必要な許可と全く同じである。)
返り値
成功すると、 process_vm_readv() は読み出したバイト数を返し、 process_vm_writev() は書き込 んだバイト数を返す。 この返り値は、 読み出し/書き込みが部分的に行われた場合には、 要求され た総バイト数よりも小さくなることがある (部分的な転送は iovec 要素単位に行われ、 これらのシ ステムコールが一つの iovec 要素の一部だけが転送されることはない)。 呼び出し元は返り値を検 査して、 部分的な読み出し/書き込みが起こったかどうかを判定できる。 エラーの場合は -1 が返され、 errno が適切に設定される。
エラー
EINVAL local_iov か remote_iov のいずれかの iov_len の合計値が ssize_t で表現できる値を超 えている。 EINVAL flags が 0 でない。 EINVAL liovcnt か riovcnt が大きすぎる。 EFAULT local_iov で指定されたメモリーが呼び出し元がアクセス可能なアドレス空間の外にある。 EFAULT remote_iov で指定されたメモリーがプロセス pid がアクセス可能なアドレス空間の外にあ る。 ENOMEM iovec 構造体の内部コピーのためのメモリーを割り当てできなかった。 EPERM 呼び出し側がプロセス pid のアドレス空間に対するアクセス許可を 持っていない。 ESRCH ID が pid のプロセスが存在しない。
バージョン
これらのシステムコールは Linux 3.2 で追加された。ライブラリによる サポートは glibc バー ジョン 2.15 以降で提供されている。
準拠
これらのシステムコールは非標準で Linux による拡張である。
注意
process_vm_readv() と process_vm_writev() により実行されるデータ転送をどのように行ったとし ても、 これらがアトミックに行われる保証はない。 これらのシステムコールは、 (共有メモリーやパイプなどを使った場合に必要となる 2 回のコピー ではなく) 1 回のコピー処理でメッセージの交換を許すことで、 高速なメッセージ送信をできるよ うにするために設計された。
例
以下のサンプルコードは 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)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクト の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。