2017-06-13 3 views
1

上記のマニュアルsplice()は、2つの任意のフィールド記述子の間でデータを転送することもできます。また、socketfdにもデータを転送することができます。これは、ファイルを一度に送信する場合に有効です。したがって、ファイルサイズはPIPE_BUF_SZ(= 65536)より小さくなければなりません。socketfdにスプライスする方法は?

しかし、大きなファイルを処理するにはどうすればよいですか? sendfile()のシステムコールとの違いを理解したい。 sendfile()システムコールはどのように書き換えますか?

2番目のスプライスはInvalid argumentで戻ります。私はsocketfdがシークできないためだと思います。

size_t len = 800000; //e.g. 
static int do_copy(int in_fd, int out_fd) 
{ 
    loff_t in_off = 0, out_off = 0; 
    static int buf_size = 65536; 
    off_t len; 
    int filedes[2]; 
    int err = -1; 

    if(pipe(filedes) < 0) { 
     perror("pipe:"); 
     goto out; 
    } 

    while(len > 0) { 
     if(buf_size > len) buf_size = len; 
     /* move to pipe buffer. */ 
     err = splice(in_fd, &in_off, filedes[1], NULL, buf_size, SPLICE_F_MOVE | SPLICE_F_MORE); 
     if(err < 0) { 
      perror("splice:"); 
      goto out_close; 
     } 
     /* move from pipe buffer to out_fd */ 
     err = splice(filedes[0], NULL, out_fd, &out_off, buf_size, SPLICE_F_MOVE | SPLICE_F_MORE); 
     if(err < 0) { 
      perror("splice2:"); 
      goto out_close; 
     } 
     len -= buf_size; 
    } 
    err = 0; 
    out_close: 
    close(filedes[0]); 
    close(filedes[1]); 

    out: 
    return err; 
} 
+0

これはmanページのものです。 'EINVALターゲットファイルシステムはスプライシングをサポートしていません。ターゲットファイルは、追加モードで開かれた です。どちらのファイル記述子も パイプを参照していません。非セカンダリデバイスに指定されたオフセット。 – vtha

+0

Thx @vtha。上で述べたように、socketfdは見分けがたいようです。しかし、sendfile()は全く同じ設定+オフセットで動作します!私が理解しているように、sendfile()は、splice()を使用して、多かれ少なかれラッパーです。興味深い。 –

+1

私はワークステーションでテストしなければならないでしょう。 – vtha

答えて

0

sendfile() systemcallは、ファイル記述子がシーク可能であるかどうかをチェックしません。そのfdへの唯一のチェックは、あなたがfdに(FMODE_READ)を読むことができるならばです。

splice()さらにチェックします。とりわけ、fdがシーク可能である(FMODE_ P READ)/(FMODE_ P書き込み)。

sendfileは機能しますが、スプライスは機能しません。

関連する問題