Linux Man на русском

  User    Syst    Libr    Device    Files    Other    Admin  



   splice - подключает данные к каналу/выбирает данные из канала

splice(2) подключает данные к каналу/выбирает данные из канала


ОБЗОР

#define _GNU_SOURCE /* см. 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 представляет собой битовую маску, которая составляется логическим сложением (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, и операция вызвала бы блокировку.

    EBADF Один или оба файловых дескриптора недействительны или в неправильном режиме чтения-записи.

    EINVAL Файловая система назначения не поддерживает соединение (splicing); файл назначения открыт в режиме добавления; ни один из файловых дескрипторов не ссылается на канал; или указано смещение, но устройство не поддерживает поиск.

    ENOMEM Не хватает памяти.

    ESPIPE Значение off_in или off_out не равно NULL, но соответствующий файловый дескриптор ссылается на канал.

    ВЕРСИИ

    Системный вызов splice() впервые появился в Linux 2.6.17; поддержка в glibc добавлена в версии 2.5.


    СООТВЕТСТВИЕ СТАНДАРТАМ

    Данный вызов есть только в Linux.


    ЗАМЕЧАНИЯ

    Три системных вызова — splice(), vmsplice(2), and tee(2), предоставляют пользовательским программам полный контроль над произвольным буфером ядра; они реализованы в ядре на базе того же типа буферов, который используется для канала. Эти системные вызовы выполняют следующие задачи:

    splice() перемещает данные из буфера в произвольный файловый дескриптор или наоборот, и из одного буфера в другой.

    tee(2) «копирует» данные из одного буфера в другой.

    vmsplice(2) «копирует» данные из пользовательского пространства в буфер.

    Хотя мы говорим о копировании, на самом деле копирования, обычно, не происходит. Ядро реализует канальный буфер как набор указателей со счётчиком ссылок на страницы памяти ядра. Ядро создаёт «копии» страниц в буфере посредством создания новых указателей (для выходного буфера), указывающих на страницы, и увеличивает счётчики ссылок страниц: копируются только указатели, а не страницы буфера.


    ПРИМЕР

    См. tee(2).