splice -
подключает
данные к
каналу/выбирает
данные из
канала
Standard C library (
libc,
-lc)
#define _GNU_SOURCE /* см. feature_test_macros(7) */
#include <fcntl.h>
ssize_t splice(int fd_in, off64_t *_Nullable off_in,
int fd_out, off64_t *_Nullable 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
представляет
собой
битовую
маску,
которая
составляется
логическим
сложением (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, но
соответствующий
файловый
дескриптор
ссылается
на канал.
The
splice() system call first appeared in Linux 2.6.17; library support
was added in glibc 2.5.
Данный
вызов есть
только в Linux.
Три
системных
вызова —
splice(),
vmsplice(2), and
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)
Русский
перевод
этой
страницы
руководства
был сделан
Alexander Golubev <
[email protected]>, Azamat Hackimov
<
[email protected]>, Hotellook, Nikita
<
[email protected]>, Spiros Georgaras <
[email protected]>, Vladislav
<
[email protected]>, Yuri Kozlov <
[email protected]>
и Иван
Павлов <
[email protected]>
Этот
перевод
является
бесплатной
документацией;
прочитайте
Стандартную
общественную
лицензию GNU
версии 3
или более
позднюю,
чтобы
узнать об
условиях
авторского
права. Мы не
несем
НИКАКОЙ
ОТВЕТСТВЕННОСТИ.
Если вы
обнаружите
ошибки в
переводе
этой
страницы
руководства,
пожалуйста,
отправьте
электронное
письмо на
[email protected]