如何拼接到socketfd上?

How to splice onto socketfd?

提到的手册 splice() 可以在两个任意文件描述符之间传输数据,也可以传输到 socketfd 上。如果立即发送文件,则此方法有效。因此文件大小必须小于 PIPE_BUF_SZ (=65536).

但是,如何处理更大的文件?我想了解与 sendfile() 系统调用的区别。您将如何重写 sendfile() 系统调用?

第二次拼接returns与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;
}

sendfile() 系统调用不检查文件描述符是否可查找。对该 fd 的唯一检查是,如果您可以将 (FMODE_READ) 读入 fd。

splice() 进行更多检查。其中,如果 fd 是可搜索的 (FMODE_PREAD) / (FMODE_PWRITE).

这就是为什么 sendfile 有效,但 splice 无效的原因。