2017-06-13 37 views
1

手冊中提到的splice()可以在兩個任意文件描述符之間傳輸數據,也可以傳輸到socketfd上。如果文件一次發送,這將起作用。因此文件大小必須低於PIPE_BUF_SZ(= 65536)。如何拼接到socketfd上?

但是,如何處理更大的文件?我想了解與sendfile()系統調用的區別。你將如何重寫sendfile()系統調用?

第二次拼接以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

這是來自手冊頁: 'EINVAL目標文件系統不支持拼接;目標文件是 以追加模式打開;這兩個文件描述符都沒有引用 一個管道;或給予不可搜索設備的偏移量。「# – vtha

+0

Thx @vtha。如上所述,socketfd似乎是不可搜索的。但是,sendfile()與完全相同的設置+偏移一起工作!據我瞭解,sendfile()或多或少是一個包裝,使用splice()。 –

+1

有趣。我將不得不在我的工作站上測試它。 – vtha

回答

0

sendfile() systemcall不檢查文件描述符是否可查找。如果你可以讀取(FMODE_READ)到fd上,唯一的檢查就是fd。

splice()做了一些更多的檢查。其中,如果fd是可尋址的(FMODE_ P READ)/(FMODE_ P WRITE)。

這就是爲什麼sendfile有效,但拼接不會。