SPLICE - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
拼接-往/从管道拼接数据
语法
#define _GNU_SOURCE /* See 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()在两个文件描述符之间移动数据,而无需在内核地址空间和用户地址空间之间进行复制。它将最多len字节的数据从文件描述符fd_in传输到文件描述符fd_out,其中文件描述符之一必须引用管道。
以下语义适用于fd_in和off_in:
- *
- 如果fd_in引用管道,则off_in必须为NULL。
- *
- 如果fd_in不引用管道并且off_in为NULL,则从fd_in读取字节(从文件偏移量开始),并适当调整文件偏移量。
- *
- 如果fd_in不引用管道并且off_in不为NULL,则off_in必须指向一个缓冲区,该缓冲区指定将从fd_in中读取字节的起始偏移量;在这种情况下,fd_in的文件偏移不会更改。
类似的语句适用于fd_out和off_out。
flags参数是一个位掩码,由以下零个或多个以下值组成或:
- SPLICE_F_MOVE
- 尝试移动页面而不是复制页面。这只是对内核的提示:如果内核无法从管道中移出页面,或者管道缓冲区未引用完整页面,则仍可以复制页面。这个标志的最初实现是有缺陷的:因此从Linux 2.6.21开始,它是一个no-op(但是仍然可以在splice()调用中允许);将来可能会恢复正确的实现。
- SPLICE_F_NONBLOCK
- 不要阻塞I / O。这使拼接管道操作成为非阻塞,但是splice()仍可能会阻塞,因为与之连接或从中进行拼接的文件描述符可能会阻塞(除非已设置O_NONBLOCK标志)。
- SPLICE_F_MORE
- 更多数据将在后续拼接中显示。当fd_out引用套接字时,这是一个有用的提示(另请参见send(2)中的MSG_MORE描述和tcp(7)中的TCP_CORK描述)。
- SPLICE_F_GIFT
- 未用于splice();请参见vmsplice(2)。
返回值
成功完成后,splice()返回与管道进行拼接的字节数。
返回值0表示输入结束。如果fd_in指向管道,则意味着没有数据要传输,并且没有意义进行阻塞,因为没有写入器连接到管道的写入端。
发生错误时,splice()返回-1并将errno设置为指示错误。
错误说明
- EAGAIN
- 在标志中指定了SPLICE_F_NONBLOCK或已将文件描述符之一标记为非阻塞(O_NONBLOCK),并且该操作将阻塞。
- EBADF
- 一个或两个文件描述符无效,或者没有正确的读写模式。
- EINVAL
- 目标文件系统不支持拼接。
- EINVAL
- 目标文件以追加模式打开。
- EINVAL
- 文件描述符均未引用管道。
- EINVAL
- 为不可搜寻的设备(例如管道)提供了偏移量。
- EINVAL
- fd_in和fd_out引用同一管道。
- ENOMEM
- 内存不足。
- ESPIPE
- off_in或off_out都不为NULL,但是相应的文件描述符引用管道。
版本
splice()系统调用首次出现在Linux 2.6.17中;库支持已在2.5版中添加到glibc。
遵循规范
此系统调用是特定于Linux的。
备注
这三个系统调用splice(),vmsplice(2)和tee(2)向用户空间程序提供对任意内核缓冲区的完全控制,该内核在内核中使用与管道相同的缓冲区类型实现。总的来说,这些系统调用执行以下任务:
- *
- splice()将数据从缓冲区移到任意文件描述符,反之亦然,或从一个缓冲区移到另一个。
- *
- tee(2)将数据从一个缓冲区"复制"到另一个缓冲区。
- *
- vmsplice(2)将数据从用户空间"复制"到缓冲区。
尽管我们谈论复制,但通常避免使用实际副本。内核通过将管道缓冲区实现为一组指向内核内存页面的引用计数指针来实现此目的。内核通过创建引用页面的新指针(用于输出缓冲区)并增加页面的引用计数来在缓冲区中创建页面的"副本":仅复制指针,而不复制缓冲区的页面。
在Linux 2.6.30和更早版本中,fd_in和fd_out中的一个必须是管道。从Linux 2.6.31开始,两个参数都可以引用管道。
示例
参见tee(2)。
另外参见
copy_file_range(2),sendfile(2),tee(2),vmsplice(2),pipe(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。