欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Linux指南:sendfile(2)函数的翻译与解读

最编程 2024-07-24 12:01:14
...

\color{#A00000}{NAME}
sendfile - transfer data between file descriptors

\color{#A00000}{SYNOPSIS}

#include <sys/sendfile.h>

ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);

\color{#A00000}{DESCRIPTION}
sendfile() 在一个文件描述符和另一个文件描述符之间复制数据。 因为这种复制是在内核中完成的,所以 sendfile() 比 read(2) 和 write(2) 的组合更有效,后者需要将数据传入和传出用户空间。

in_fd 是一个为读取而打开的文件描述符,out_fd 是一个为写入而打开的描述符。

如果 offset 不为NULL,则sendfile()将以其为偏移量从in_fd中读取数据。当 sendfile() 返回时,此变量将设置为读取的最后一个字节之后的偏移量。 如果 offset 为 NULL,则将从 in_fd 中的文件偏移量开始读取数据。

需要注意!如果指定了offset,那么读取 in_fd中的数据是不会修改其打开文件自身的偏移量的。

count 是要在文件描述符之间复制的字节数。

in_fd 参数必须是支持类似 mmap(2) 等操作的文件(即它不能是套接字)。

在 2.6.33 之前的 Linux 内核中,out_fd 必须引用套接字。 从 Linux 2.6.33 开始,它可以是任何文件。 如果它是一个常规文件,则 sendfile() 适当地更改out_fd的文件偏移量。

\color{#A00000}{RETURN VALUE}
如果传输成功,则返回写入 out_fd 的字节数。 请注意,成功调用 sendfile() 可能会写入比请求更少的字节; 如果有未发送的字节,调用者应该准备重试调用。 另见NOTES。
出错时,返回 -1,并设置 errno 以指示错误。

\color{#A00000}{ERRORS}

  • EAGAIN
    Nonblocking I/O has been selected using O_NONBLOCK and the write would block.

  • EBADF
    输入文件或输出文件未打开。

  • EFAULT
    Bad address.

  • EINVAL
    描述符无效或被锁定,或者类似 mmap(2) 的操作对 in_fd 不可用,或者计数为负数。

  • EINVAL
    out_fd 设置了 O_APPEND 标志。 sendfile() 当前不支持此功能。

  • EIO
    从 in_fd 读取时出现未指定的错误。

  • ENOMEM
    Insufficient memory to read from in_fd.

  • EOVERFLOW
    计数太大,操作将导致超过输入文件或输出文件的最大大小。

  • ESPIPE
    offset 不是 NULL 但输入文件is not seekable.

\color{#A00000}{VERSIONS}
sendfile() 首次出现在 Linux 2.2 中。 从 glibc 2.1 开始就存在包含文件 <sys/sendfile.h>。

\color{#A00000}{CONFORMING TO}
Not specified in POSIX.1-2001, nor in other standards.

Other UNIX systems implement sendfile() with different semantics and prototypes. It should not be used in portable programs.

\color{#A00000}{NOTES}
sendfile() 最多传输 0x7ffff000 (2,147,479,552) 个字节,返回的是实际传输的字节数。 (在 32 位和 64 位系统上都是如此。)

如果您计划使用 sendfile() 将文件发送到 TCP 套接字,但需要在文件内容之前发送一些标头数据,您会发现使用 TCP_CORK 选项很有用,在 tcp(7) 中描述,以最小化 数据包的数量并调整性能。

根据tcp(7),TCP_CORK的作用是:如果设置,则不发送部分帧。 当再次清除该选项时,将发送所有排队的部分帧。更方便的,可以在执行时send()时设置MSG_MORE标志,见send(2)

在 Linux 2.4 及更早版本中,out_fd 也可以指普通文件; 这种可能性在 Linux 2.6.x 内核系列中消失了,但在 Linux 2.6.33 中恢复了。

最初的 Linux sendfile() 系统调用不是为了处理大文件偏移量而设计的。 因此,Linux 2.4 添加了 sendfile64(),偏移参数的类型更宽。 glibc sendfile() 包装函数透明地处理内核差异。

在 sendfile() 因 EINVAL 或 ENOSYS 失败的情况下,应用程序可以回退到 read(2)/write(2)。

如果 out_fd 引用了具有零拷贝支持的套接字或管道,则调用者必须确保 in_fd 引用的文件的传输部分保持不变,直到 out_fd 另一端的读取器消耗了传输的数据。

Linux 特定的 splice(2) 调用支持在任意文件描述符之间传输数据,前提是其中一个(或两个)是管道。

推荐阅读