SENDFILE(2)

名称
sendfile - ファイルをソケットに送信

ライブラリ
libc

書式
<sys/types.h> <sys/socket.h> <sys/uio.h> int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags)

解説
sendfile() システムコールは、記述子 fd によって指定された通常のファイルを、記述子 s によって指定されたストリームソケットから送信します。

offset 引数はファイルのどこから開始すべきかを指定します。 nbytes 引数は、ファイルの何バイトを送信する必要があるかを指定します。 0 は、ファイルの終わりまで送信するという特殊な意味を持ちます。

オプションのヘッダまたはトレーラ、またはその両方は、構造体 sf_hdtr を 指すポインタを指定することによってファイルの前と後で送信できます。 構造体 sf_hdtr の構造は次のとおりです:

    struct sf_hdtr {
    	struct iovec *headers;  /* ヘッダ iovecs を指すポインタ */
    	int hdr_cnt;            /* ヘッダ iovecs の数 */
    	struct iovec *trailers; /* トレーラ iovecs を指すポインタ */
    	int  trl_cnt;           /* トレーラ iovecs の数 */
    };

headers ポインタと trailers ポインタは、NULL でない場合に構造体 iovec 構造の配列を指します。 iovec 構造体の詳細については、 writev() システムコールを参照してください。 これらの配列内の iovecs の数は、 hdr_cnt と trl_cnt によって指定されます。

NULL でない場合に、システムは、ソケット上に送信された合計バイト数を、 sbytes によって指された変数に書き込みます。

flags 引数は現時点では未定義であり、0 に指定する必要があります。

非ブロッキング入出力用に指定されたソケットを使用するときに、 sendfile() は要求されたよりも少ないバイトを送信することがあります。 この場合、正常に書き込まれたバイト数が *sbytes (指定されている場合) に返され、エラー EAGAIN が返されます。

実装に関する注
sendfile() の FreeBSD での実装は「0 コピー」です。 すなわち、ファイルデータのコピーが回避されるように最適化されています。

チューニング
内部ではこのシステムコールは、クライアントへの送信ファイルデータを 取り扱うために、特別な sendfile(2) バッファ (struct sf_buf) を使用しています。 送信ソケットがブロックされていて、 利用可能な送信ファイルバッファが十分でない場合には、 sendfile(2) はブロックされ、 “sfbufa” の状態を報告します。 送信ソケットがブロックされておらず、 利用可能な送信ファイルバッファが十分でない場合には、 この呼び出しはブロックされ、呼び出しを終了する前に必要なバッファが 利用可能になるのを待ちます。

sf_buf の割り当てられた数は、 sendfile(2) を介してクライアントにデータを送信するために使用される nmbclusters の数に、 比例しているべきです。 ブロッキングを避けるために適宜にチューンしましょう! sendfile(2) を広範囲に使用する忙しい装置が、 kern.ipc.nmbclusters に展開されるこれらの値を増加させたくなるかもしれません (詳細は tuning(7) を参照してください)。

使用中の sendfile(2) バッファの数は、 loader.conf(5) の中の kern.ipc.nsfbufs 変数または NSFBUFS カーネルコンフィギュレーション調整のどちらかによって、ブート時に決定されます。 sendfile バッファの数は kern.maxusers に合わせて調整されます。

戻り値

エラー

[EBADF]
    fd 引数が有効なファイル記述子ではありません。

[EBADF]
    s 引数が有効なソケット記述子ではありません。

[ENOTSOCK]
    s 引数がソケットではありません。

[EINVAL]
    fd 引数が通常のファイルではありません。

[EINVAL]
    s 引数が SOCK_STREAM 型のソケットではありません。

[EINVAL]
    offset 引数が負であるか、または範囲外です。

[ENOTCONN]
    s 引数が、未接続のソケットを指しています。

[EPIPE]
    通信相手が接続を閉じてしまいました。

[EIO]
    fd から読取り中に入出力エラーが発生しました。

[EFAULT]
    引数について無効なアドレスが指定されました。

[EAGAIN]
    ソケットは非ブロッキング入出力と指定されており、ソケットバッファが 満杯であるためにすべてのデータが送信されませんでした。 sbytes が指定された場合、送信が正常に完了したバイト数が *sbytes 内に返されます。

関連項目
open(2), send(2), socket(2), writev(2), tuning(7)

歴史
sendfile() システムコールは、 FreeBSD 3.0 ではじめて登場しました。 このマニュアルページは FreeBSD 3.1 ではじめて登場しました。

作者
sendfile() システムコールとこのマニュアルページは David Greenman <dg@root.com> が作成しました。