Provided by: manpages-ja-dev_0.5.0.0.20180315+dfsg-1_all bug

名前

       readv, writev, preadv, pwritev - 複数のバッファーへの読み書きを行なう

書式

       #include <sys/uio.h>

       ssize_t readv(int fd, const struct iovec *iov, int iovcnt);

       ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

       ssize_t preadv(int fd, const struct iovec *iov, int iovcnt,
                      off_t offset);

       ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt,
                       off_t offset);

   glibc 向けの機能検査マクロの要件 (feature_test_macros(7)  参照):

       preadv(), pwritev(): _BSD_SOURCE

説明

       readv()  システムコールは、ファイルディスクリプター  fd  に関連付けられた  ファイルから、 iovcnt 個のバッ
       ファー分のデータを読み込み、 iov で指定 されたバッファーに格納する ("scatter input";「ばらまき入力」)。

       writev() システムコールは、 iov  で指定されたバッファーから最大  iovcnt  個のバッファー分のデータを取り出
       し、 ファイルディスクリプター fd に関連付けら れたファイルに書き込む ("gather output";「かき集め出力」)。

       ポインター  ioviovec 構造体の配列へのポインターである。 iovec 構造体は <sys/uio.h> で以下のように定義
       されている:

           struct iovec {
               void  *iov_base;    /* Starting address */
               size_t iov_len;     /* Number of bytes to transfer */
           };

       readv() システムコールは、複数のバッファーにデータを読み込む点を除いて read(2) と全く同様の動作を行う。

       writev() システムコールは、複数のバッファーのデータを書き出す点以外は write(2) と全く同様の動作を行う。

       バッファーは配列の順序で処理される。これは、 readv()   が  iov[0]  が完全に一杯になるまでデータを詰めてか
       ら、 iov[1] などに進むことを意味する (データが十分ない場合は、 iov が指すバッファーのいずれも一杯にならな
       い)。 同様に、 writev()  は iov[0] の内容を全部書き出してから iov[1] などに進む。

       readv()  と writev()  によるデータ転送は atomic に行われる。つまり、 writev()  によるデータ書き込みは一つ
       のブロックとして行われ、他のプロセスの write による書き込みと混ざり合うことはない (例外に関しては pipe(7)
       を参照のこと)。同様に、 readv()  はファイルから連続するデータブロックが読み出すことが保証され、  同じファ
       イル記述 (file description; open(2)  参照) を参照するファイルディスクリプターを持つ他のスレッドやプロセス
       が 実行した read 操作の影響を受けることはない。

   preadv()  pwritev()
       preadv() システムコールは readv() と preadv(2) の機能を 組み合わせたものである。 readv() と同じ処理を実行
       するが、  4  番目の引き数  offset が追加されており、 この引き数は入力操作を行うファイルオフセットを指定す
       る。

       pwritev() システムコールは writev() と pwrite(2) の機能を 組み合わせたものである。 writev()  と同じ処理を
       実行するが、  4 番目の引き数 offset が追加されており、 この引き数は出力操作を行うファイルオフセットを指定
       する。

       これらのシステムコールで、ファイルオフセットは変更されない。 fd が参照するファイルは seek  可能でなければ
       ならない。

返り値

       成功した場合、 readv() と preadv は読み込んだバイト数を返し、 writev() と pwritev()は書き込んだバイト数を
       返す。 エラーの場合 -1 を返し、errno を適切に設定する。

エラー

       read(2)  や write(2)  と同じエラーが定義されている。 さらに、 preadv() と pwritev() は lseek(2)  と同じ理
       由でも失敗する。 また、追加で以下のエラーが定義されている:

       EINVAL iov_len の合計が ssize_t の範囲をオーバーフローした。

       EINVAL ベクタ数 iovcnt が 0 より小さいか許可された最大値よりも大きかった。

バージョン

       preadv() と pwritev() は Linux 2.6.30 で初めて登場した。 ライブラリによるサポートは glibc 2.10 で追加され
       た。

準拠

       readv(), writev(): 4.4BSD (これらのシステムコールは 4.2BSD で初めて登場した), POSIX.1-2001.

       preadv(), pwritev(): 非標準だが、最近の BSD にも存在する。

注意

       POSIX.1-2001 では、 iov で渡すことができる要素数に上限を設ける実装が認められている。 実装はこの上限値を広
       告することができ、  <limits.h>IOV_MAX を定義することや、 実行時に sysconf(_SC_IOV_MAX) の返り値経由で
       知ることができる。 最近の Linux では、 この上限値は 1024 である。 Linux 2.0 の頃は、 この値は  16  であっ
       た。

   C ライブラリとカーネル ABI の違い
       素のシステムコール preadv() と pwritev() のシグネチャーは、 「書式」に書かれている対応する GNU C ライブラ
       リのラッパー関数のものとは少し異なる。 最後の引き数 offset はラッパー関数によりシステムコールの 2  つの引
       き数に展開される。

        unsigned long pos_l, unsigned long pos

       これらの引き数は、それぞれ、 offset の下位 32 ビットと上位 32 ビットである。

   以前の C ライブラリとカーネル ABI の違い
       古いバージョンの  Linux  では  IOV_MAX  が非常に小さかったという事実に対処するため、  glibc の readv() と
       writev() のラッパー関数は、  その関数の内部で呼ばれるカーネルシステムコールがこの上限を超過して失敗したこ
       とを検出すると、  追加の動作をしていた。 readv() の場合、 ラッパー関数は iov で指定された全ての要素を格納
       できる大きさの一時バッファーを割り当て、  read(2)  を呼び出す際にそのバッファーを渡し、  そのバッファーの
       データを  iov  の各要素の  iov_base フィールドが指定する場所にコピーしてから、 そのバッファーを解放してい
       た。 writev() のラッパー関数も、 同じように一時バッファーを使って write(2) を呼び出していた。

       glibc ラッパー関数でのこの追加の動作は Linux 2.2  以降では必要なくなった。  しかし、  glibc  はバージョン
       2.10  まではこの動作を続けていた。 glibc 2.9 以降では、 システムがバージョン 2.6.18 より前の Linux カーネ
       ル  (2.6.18  は勝手に選択したカーネルバージョンである)   を実行しているとライブラリが検出した場合にのみ、
       ラッパー関数はこの動作を行う。  glibc 2.20 以降では、 (Linux カーネルのバージョン 2.6.32 以降が必須条件と
       なり) glibc のラッパー関数は常にシステムコールを直接呼び出すようになっている。

バグ

       ファイルディスクリプターに対する操作を行う readv() や writev() と、  標準入出力ライブラリの関数をごちゃま
       ぜにして呼ぶのはお薦めしない。  どんな結果になるかは定義されておらず、おそらく期待する結果は 得られないだ
       ろう。

       以下のサンプルコードは writev()  の使用方法を示すものである。

           char *str0 = "hello ";
           char *str1 = "world\n";
           struct iovec iov[2];
           ssize_t nwritten;

           iov[0].iov_base = str0;
           iov[0].iov_len = strlen(str0);
           iov[1].iov_base = str1;
           iov[1].iov_len = strlen(str1);

           nwritten = writev(STDOUT_FILENO, iov, 2);

関連項目

       pread(2), read(2), write(2)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告
       に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。