sendfile -
ファイル・ディスクリプタ間でデータを転送する
#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t
* offset, size_t count);
sendfile()
は、あるファイル・ディスクリプタから別の
ファイル・ディスクリプタへのデータのコピーを行う。
このコピーはカーネル内で行われるので、
sendfile() は、
read(2) と
write(2)
を組み合わせるよりも効率がよい。
read(2) や
write(2)
ではユーザ空間との間でデータの転送が必要となるからである。
in_fd
は読み込みのためにオープンされたファイル・ディスクリプタ、
out_fd
は書き込みのためにオープンされたディスクリプタでなければならない。
offset が NULL でない場合、
offset は
sendfile() が
in_fd
のどこからデータを読み始めるかを示すファイル・オフセットを保持する変数への
ポインタである。
sendfile()
は復帰する時、この変数に最後に読み込んだバイトの
次のバイトのオフセットを書き込む。
offset が NULL でない場合、
sendfile() は
in_fd
のファイル・オフセットの現在値を変更しない。
NULL
の場合は、ファイル・オフセットの現在値を
in_fd
から読み込んだバイト数を反映した位置に調整する。
offset が NULL
の場合、データは
in_fd
の現在のファイル・オフセットから読み出され、
ファイル・オフセットはこの呼び出しで更新される。
count
は、ファイル・ディスクリプタ間でコピーするバイト数である。
in_fd 引き数は
mmap(2)
風の操作ができるファイルを指していなければならな
い
(ソケットを指定することはできない)。
2.6.33 より前の Linux
カーネルでは
out_fd
はソケットを参照していなければな
らない。Linux 2.6.33
以降では、任意のファイルを参照することができる。
通常のファイルの場合には
sendfile()
はファイルオフセットを適切に変更する。
返り値¶
転送に成功した場合、
out_fd
に書き込まれたバイト数を返す。エラーの場合、-1
を返し、
errno
に適切な値を設定する。
エラー¶
- EAGAIN
- O_NONBLOCK
を用いて非ブロック
I/O
が選択されたが、書き込みがブロックされた。
- EBADF
- 入力ファイルが読み込みのためにオープンされていないか、
出力ファイルが書き込みのためにオープンされていない。
- EFAULT
- アドレスがおかしい。
- EINVAL
- ディスクリプタが有効でないか、ロックされている。もしくは
mmap(2) 風の操作が in_fd
では利用できない。
- EIO
- in_fd
から読み込んでいるうちに予期しないエラーが起こった。
- ENOMEM
- in_fd
から読み込むための十分なメモリがない。
バージョン¶
sendfile は Linux 2.2
の新しい機能である。
インクルードファイル
<sys/sendfile.h> は glibc 2.1
から存在している。
POSIX.1-2001
や他の標準では規定されていない。
他の UNIX
システムでは、異なった方式やプロトタイプで
sendfile()
を実装している。移植性を考慮したプログラムでは使用すべきではない。
sendfile() を使って TCP
ソケットにファイルを送ろうとしていて、
ファイルの内容の前にヘッダ・データを付け加える必要がある場合は、
パケット数を最小にして性能を上げるために
tcp(7) に記述されている
TCP_CORK
オプションを使うといいだろう。
Linux 2.4
とそれ以前のバージョンでも、
out_fd
は通常のファイルを参照でき、
sendfile()
はそのファイルのオフセットの現在値を変更していた。
元々の Linux
sendfile()
システムコールは大きなファイルオフセットを
扱えるように設計されていなかった。その結果、Linux
2.4 で、
ビット幅の大きな
offset
引き数を持った
sendfile64()
が追加された。 glibc の
sendfile()
のラッパー関数はカーネルによるこの違いを吸収している。
sendfile() が
EINVAL や
ENOSYS
で失敗するような場合は、
アプリケーションは
read(2)/
write(2)
に戻すことを考えてもよいかもしれない。
Linux 固有の
splice(2)
システムコールは、任意のファイル間
(例えば、
ソケット同士)
でのデータ転送をサポートしている。
関連項目¶
mmap(2),
open(2),
socket(2),
splice(2)
この文書について¶
この man ページは Linux
man-pages
プロジェクトのリリース
3.41 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man-pages/
に書かれている。