名 前
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";「 か き 集 め 出 力 」 )。 ポ イ ン タ ー iov は iovec 構 造 体 の 配 列 へ の ポ イ ン タ ー で あ る 。 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 の 範 囲 を オ ー バ ー フ ロ ー し た 。 ベ ク タ 数 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 "; iov[0].iov_base
= str0; nwritten = writev(STDOUT_FILENO, iov, 2); 関 連 項 目こ の 文 書 に つ い てこ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。 |