EN JA
WRITE(2)
WRITE(2) FreeBSD System Calls Manual WRITE(2)

名称

write, writev, pwrite出力の書み込み

ライブラリ

Standard C Library (libc, -lc)

書式

#include < sys/types.h>
#include < unistd.h>

ssize_t
write( int fd, const void *buf, size_t nbytes);

ssize_t
pwrite( int fd, const void *buf, size_t nbytes, off_t offset);

#include < sys/uio.h>

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

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

解説

write() システムコールは、 buf が指すバッファから記述子 fd が参照するオブジェクトに nbytes のデータを書き込もうとします。 writev() システムコールは同様の動作をしますが、iov[0], iov[1], ..., iov[iovcnt-1] という iov 配列のメンバが指定する iovcnt バッファから出力データを集めます。 pwrite() と pwritev() システムコールは同じ機能を実行しますが、ファイルポインタを修正せずに、ファイルの特定場所に書き込みます。

writev() と pwritev() では、 iovec 構造体が以下のように定義されています:

struct iovec { 
 void   *iov_base;    /* ベースアドレス */ 
 size_t  iov_len;     /* 長さ */ 
};

iovec エントリは、書き込むデータがあるメモリのベースアドレスと領域の長さを指定します。 writev() システムコールは、常に領域全体を書き込んでから次に進みます。

シーク機能があるオブジェクトでは、 write() は、 fd に関連するポインタが指定する位置で開始します。 lseek(2) を参照してください。 write() から戻ると、ポインタは書き込まれたバイト数だけ進みます。

シーク機能がないオブジェクトでは、常に現在位置から書き込みます。このようなオブジェクトに関連するポインタの値は未定義です。

実ユーザがスーパユーザでない場合、 write() は、ユーザ ID 設定ビットをファイルでクリアします。これにより、スーパユーザが所有する書み込み可能なユーザ ID 設定ファイルを“捕えた”ユーザは、システムセキュリティを突破できなくなります。

ソケットのように、フロー制御の影響を受けるオブジェクトで非ブロッキング I/O を使用すると、 write() と writev() は、要求したより少ないバイト数を書き込むことがあります。戻り値に注意し、可能な場合にはオペレーションの残りを再度試してください。

戻り値

処理が正常に完了すると、書き込まれたバイト数が返されます。そうでない場合は -1 が返され、エラーを示すためにグローバル変数 errno が設定されます。

エラー

write(), writev(), pwrite() と pwritev() システムコールは、以下の場合にエラーとなり、ファイルポインタは変更されずに残ります:
[ EBADF]
fd 引数が、書み込み用にオープンされた有効な記述子ではありません。
[ EPIPE]
プロセスによる読み込み用にオープンされていないパイプに書き込もうとしました。
[ EPIPE]
通信相手のソケットに接続していないタイプ SOCK_STREAM のソケットに書き込もうとしました。
[ EFBIG]
プロセスのファイルサイズ制限か最大ファイルサイズを越えたファイルに書き込もうとしました。
[ EFAULT]
iov の一部、またはファイルに書き込むデータは、プロセスに割り当てられたアドレス空間の範囲外を指しています。
[ EINVAL]
fd に関連するポインタが負になっています。
[ ENOSPC]
ファイルを含むファイルシステムに、充分なスペースが残っていません。
[ EDQUOT]
ファイルを含むファイルシステムのユーザのディスクブロック割当量が使い尽くされています。
[ EIO]
ファイルシステムに読み書きしている間に入出力エラーが発生しました。
[ EINTR]
書み込みが完了する前にシグナルが割り込みました。
[ EAGAIN]
ファイルは非ブロッキング入出力の印がついた状態で、しかも、すぐにデータを書き込める状態ではありません。
[ EROFS]
スライスの先頭にあるディスクラベル領域に書み込みを行おうとしました。ディスクラベル領域への書み込みを有効にするには disklabel(8) -W を参照してください。
[ EINVAL]
nbytesINT_MAX よりも大きいです。

writev() と pwritev() は、以下のエラーを返します:

[ EDESTADDRREQ]
connect(2) を使用して書み込み先アドレスを設定した UNIX ドメインデータグラムソケットに書き込む場合に、書み込み先が使用できません。
[ EINVAL]
iovcnt 引数が 0 以下になっているか、 IOV_MAX より、大きくなっています。
[ EINVAL]
iov 配列 iov_len 値の 1 つが負になっています。
[ EINVAL]
iov 配列 iov_len 値の合計が、32 ビット整数をオーバフローしました。
[ ENOBUFS]
ソケットに書き込んでいる時に mbuf のプールを使い尽くしました。

pwrite() と pwritev() システムコールは、以下のエラーを返します:

[ EINVAL]
offset の値が負です。
[ ESPIPE]
ファイル記述子が、パイプ、ソケット、FIFO に関連しています。

規格

write() システムコールは、 IEEE Std 1003.1-1990 (“POSIX.1”) に適合するはずです。 writev() と pwrite() システムコールは、 X/Open Portability Guide Issue 4, Version 2 (“XPG4.2”) に適合するはずです。

歴史

pwritev() システムコールは、 FreeBSD 6.0 で登場しました。 pwrite() 関数は、 AT&T System V Release 4 UNIX で登場しました。 writev() システムコールは、 4.2BSD で登場しました。 write() 関数は、 Version 6 AT&T UNIX で登場しました。
September 11, 2013 FreeBSD