table of contents
- Tumbleweed 4.28.0-1.1
- Leap-16.0
- Leap-15.6
| splice(2) | System Calls Manual | splice(2) |
НАИМЕНОВАНИЕ¶
splice - подключает данные к каналу/выбирает данные из канала
БИБЛИОТЕКА¶
Стандартная библиотека языка C (libc, -lc)
ОБЗОР¶
#define _GNU_SOURCE /* см. feature_test_macros(7) */ #define _FILE_OFFSET_BITS 64 #include <fcntl.h>
ssize_t splice(int fd_in, off_t *_Nullable off_in,
int fd_out, off_t *_Nullable off_out,
size_t size, unsigned int flags);
ОПИСАНИЕ¶
splice() moves data between two file descriptors without copying between kernel address space and user address space. It transfers up to size bytes of data from the file descriptor fd_in to the file descriptor fd_out, where one of the file descriptors must refer to a pipe.
К fd_in и off_in применяются следующие правила:
- •
- Если fd_in указывает на канал, то значение off_in должно быть NULL.
- •
- Если fd_in не указывает на канал и off_in равно NULL, то из fd_in читаются байты начиная с смещения файла и это смещение соответственно изменяется.
- •
- If fd_in does not refer to a pipe and off_in is not NULL, then off_in must point to a buffer which specifies the starting offset from which bytes will be read from fd_in; in this case, the file offset of fd_in is not changed, and the offset pointed to by off_in is adjusted appropriately instead.
Аналогичные правила относятся и к fd_out и off_out.
Аргумент flags представляет собой битовую маску, которая составляется логическим сложением (OR) следующих значений:
- SPLICE_F_MOVE
- Пытаться переместить страницы, а не копировать их. Используется только как подсказка ядру: страницы всё равно будут копироваться, если ядро не сможет переместить страницы из канала, или если буферы канала не ссылаются на полные страницы. Первая реализация этого флага была с дефектами: поэтому начиная с Linux 2.6.21 этот флаг ни на что не влияет (но по прежнему разрешён в вызове splice()); в будущем, возможно появится корректная реализация.
- SPLICE_F_NONBLOCK
- Не блокировать при вводе-выводе. Это делает операции соединения с каналом неблокируемыми, но splice(), тем не менее, может заблокироваться, так как файловые дескрипторы, с которыми ведётся работа, могут блокироваться (если у них не установлен флаг O_NONBLOCK).
- SPLICE_F_MORE
- В следующем подключении будут дополнительные данные. Полезно указывать, когда fd_out ссылается на сокет (смотрите также описание MSG_MORE в send(2) и описание TCP_CORK в tcp(7)).
- SPLICE_F_GIFT
- Не используется в splice(); смотрите vmsplice(2).
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ¶
При успешном выполнении splice() возвращает количество байт, которые были записаны или получены из канала.
Возвращаемое значение 0 означает конец ввода. Если fd_in указывает на канал, то это означает, что нет данных для передачи и и блокировка не имела бы смысла, так как нет писателей, подключённых к пишущему концу канала.
В случае ошибки splice() возвращает -1, а errno устанавливается в соответствующее значение.
ОШИБКИ¶
- EAGAIN
- В flags указан SPLICE_F_NONBLOCK или один из файловых дескрипторов был помечен как неблокирующий (O_NONBLOCK), и операция вызвала бы блокировку.
- EBADF
- Один или оба файловых дескриптора недействительны или в неправильном режиме чтения-записи.
- EINVAL
- Целевая файловая система не поддерживает подключение данных (splicing).
- EINVAL
- Файл назначения открыт в режиме добавления.
- EINVAL
- Ни один из файловых дескрипторов не ссылается на канал.
- EINVAL
- Указано смещение для устройства этого не поддерживающего (например, канала).
- EINVAL
- Значение fd_in и fd_out указывают на один и тот же канал.
- ENOMEM
- Не хватает памяти.
- ESPIPE
- Значение off_in или off_out не равно NULL, но соответствующий файловый дескриптор ссылается на канал.
СТАНДАРТЫ¶
Linux.
ИСТОРИЯ¶
Linux 2.6.17, glibc 2.5.
В Linux 2.6.30 и старее, только один из fd_in и fd_out должен быть каналом. Начиная с Linux 2.6.31 оба параметра должны быть каналами.
ПРИМЕЧАНИЯ¶
Три системных вызова — splice(), vmsplice(2), and tee(2), предоставляют пользовательским программам полный контроль над произвольным буфером ядра; они реализованы в ядре на базе того же типа буферов, который используется для канала. Эти системные вызовы выполняют следующие задачи:
- splice()
- перемещает данные из буфера в произвольный файловый дескриптор или наоборот, и из одного буфера в другой.
- tee(2)
- «копирует» данные из одного буфера в другой.
- vmsplice(2)
- «копирует» данные из пользовательского пространства в буфер.
Хотя мы говорим о копировании, на самом деле копирования, обычно, не происходит. Ядро реализует канальный буфер как набор указателей со счётчиком ссылок на страницы памяти ядра. Ядро создаёт «копии» страниц в буфере посредством создания новых указателей (для выходного буфера), указывающих на страницы, и увеличивает счётчики ссылок страниц: копируются только указатели, а не страницы буфера.
_FILE_OFFSET_BITS should be defined to be 64 in code that uses non-null off_in or off_out or that takes the address of splice, if the code is intended to be portable to traditional 32-bit x86 and ARM platforms where off_t's width defaults to 32 bits.
ПРИМЕРЫ¶
See tee(2) for another example.
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <err.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
int fd;
int pfd[2];
off_t off;
const char s[12] = "Hello, world";
fd = open("out", O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd == -1)
err(EXIT_FAILURE, "open");
if (pipe(pfd) == -1)
err(EXIT_FAILURE, "pipe");
if (write(pfd[1], s, sizeof(s)) != sizeof(s))
err(EXIT_FAILURE, "write");
if (close(pfd[1]) == -1)
err(EXIT_FAILURE, "close");
off = 10;
if (splice(pfd[0], NULL, fd, &off, sizeof(s), 0) != sizeof(s))
err(EXIT_FAILURE, "splice");
if (close(pfd[0]) == -1)
err(EXIT_FAILURE, "close");
printf("New offset is %jd\n", (intmax_t) off);
if (close(fd) == -1)
err(EXIT_FAILURE, "close");
exit(EXIT_SUCCESS);
}
СМОТРИТЕ ТАКЖЕ¶
copy_file_range(2), sendfile(2), tee(2), vmsplice(2), pipe(7)
ПЕРЕВОД¶
Русский перевод этой страницы руководства разработал(и) Alexander Golubev <fatzer2@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Hotellook, Nikita <zxcvbnm3230@mail.ru>, Spiros Georgaras <sng@hellug.gr>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов <pavia00@gmail.com> и Kirill Rekhov <krekhov.dev@gmail.com>
Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков.
| 17 мая 2025 г. | Справочные страницы Linux (невыпущенные) |