SPLICE(2) | Linux Programmer's Manual | SPLICE(2) |
名前
splice -パイプとの間でデータを継ぎ合わせる書式
#define _GNU_SOURCE /* feature_test_macros(7) 参照 */
#include <fcntl.h>
ssize_t splice(int fd_in, loff_t *off_in, int fd_out,
loff_t *off_out, size_t len, unsigned int flags);
説明
splice() は、カーネルアドレス空間とユーザアドレス空間との間のコピーを伴わずに、 2 つのファイルディスクリプタ間でデータの移動を行う。ファイルディスクリプタ fd_in からファイルディスクリプタ fd_out へ最大 len バイトを転送する。 2 つのファイルディスクリプタのうち一つはパイプを参照していなければならない。- SPLICE_F_MOVE
- ページのコピーでなく移動を試みる。これはカーネルに対するヒントでしかない。つまり、カーネルがパイプからページを移動できない場合や、パイプバッファがページ全部を参照していない場合は、ページのコピーが行われることもある。このフラグの最初の実装にはバグがあった。そのため、 Linux 2.6.21 以降ではこのフラグの操作はできないようになっている (ただし、 splice() コールでこのフラグを指定することは今も認められている)。将来、正しい実装が行われることだろう。
- SPLICE_F_NONBLOCK
- 入出力時に停止 (block) しない。このフラグを指定すると、 splice によるパイプ操作を非停止モード (nonblocking) で行おうとするが、その場合でも splice() は停止することもある。なぜなら、データのやり取りを行うファイルディスクリプタは ( O_NONBLOCK フラグをセットされていない場合) 停止する可能性があるからである。
- SPLICE_F_MORE
- この後の splice でさらに転送されるデータがあることを示す。このフラグは fd_out がソケットを参照している場合に有用なヒントとなる ( send(2) の MSG_MORE や tcp(7) の TCP_CORK の説明も参照)。
- SPLICE_F_GIFT
- splice() では使用しない。 vmsplice(2) 参照。
返り値
成功して完了すると、 splice() はパイプから出し入れしたバイト数を返す。返り値 0 はデータの転送が行わなかったことを示す。この場合、処理を停止 (block) しても無意味である。なぜなら、 fd_in が参照するパイプの書き込み側に接続されている者がいないからである。エラー
- EBADF
- ファイルディスクリプタの一方または両方が有効ではない、もしくは適切な read-write モードではない。
- EINVAL
- 対象のファイルシステムが splice に対応していない、または対象のファイルが追記モードでオープンされている、またはディスクリプタのどちらもパイプを参照していない、または seek できないデバイスに対してオフセットが指定された。
- ENOMEM
- メモリ不足。
- ESPIPE
- off_in か off_out のいずれかが NULL ではないが、対応するファイルディスクリプタがパイプを参照している。
バージョン
splice() システムコールは Linux 2.6.17 で初めて登場した。ライブラリによるサポートは glibc バージョン 2.5 で追加された。準拠
このシステムコールは Linux 固有である。注意
3 つのシステムコール ( splice(), vmsplice(2), tee(2)) を使うと、ユーザ空間プログラムは任意のカーネルバッファに対する完全な制御ができる。カーネルバッファは、パイプに使用されているのと同種のバッファを使ってカーネル内に実装されている。大まかにいうと、これらのシステムコールは以下の仕事を行う:- splice()
- バッファから任意のファイルディスクリプタや、その逆方向、もしくはあるバッファから別のバッファへの、データ移動を行う。
- tee(2)
- あるバッファから別のバッファへのデータ「コピー」を行う。
- vmsplice(2)
- ユーザ空間からバッファへのデータ「コピー」を行う。
ここではコピーの話をしているが、実際のコピーは一般的に回避される。カーネルは、パイプ・バッファをカーネルメモリのページへのポインタ集合として実装し、ページへの参照回数を管理することで、これを実現している。カーネルは、対象となるページを参照する (出力バッファ用の) ポインタを新規に作成することでバッファ内のページの「コピー」を作成し、そのページの参照回数を増やす。つまり、ポインタだけがコピーされ、バッファのページはコピーされない。
例
tee(2) 参照。関連項目
sendfile(2), tee(2), vmsplice(2)この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2012-05-04 | Linux |