Scroll to navigation

SENDFILE(2) Руководство программиста Linux SENDFILE(2)

ИМЯ

sendfile - производит обмен данными между дескрипторами файлов

ОБЗОР

#include <sys/sendfile.h>

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

ОПИСАНИЕ

Вызов sendfile() копирует данные из одного файлового дескриптора в другой. Так как копирование производится в ядре, использование sendfile() более эффективно чем комбинация read(2) и write(2), в которой требуется скопировать данные в и из пользовательского пространства.

В in_fd должен указываться файловый дескриптор, открытый для чтения, а в out_fd должен указываться файловый дескриптор, открытый для записи.

Если значение offset не равно NULL, то оно указывает на переменную, содержащую файловое смещение с которого sendfile() начнёт чтение данных из in_fd. При завершении sendfile() значение этой переменной будет содержать указатель на следующий байт после последнего прочитанного. Если значение offset не равно NULL, то sendfile() не изменяет текущее файловое смещение in_fd; иначе текущее файловое смещение изменяется для отражения количества прочитанных из in_fd байт.

Если значение offset равно NULL, то данные будут прочитаны из in_fd начиная с текущего файлового смещения, и по окончании работы вызова файловое смещение будет обновлено.

В count содержится количество байт, копируемых между файловыми дескрипторами.

Значение in_fd должно описывать файл, который поддерживает операции типа mmap(2) (т.е., не сокет).

В ядрах Linux до версии 2.6.33, значение out_fd должно указывать на сокет. Начиная с Linux 2.6.33 можно указывать любой файл. Если это обычный файл, то sendfile() изменит файловое смещение соответствующим образом.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

Если пересылка прошла успешно, то возвращается количество переданных в out_fd байт. При ошибке возвращается -1, а переменной errno присваивается номер ошибки.

ОШИБКИ

Был выбран неблокирующий ввод-вывод с помощью O_NONBLOCK, но запись привела бы блокировке.
Входной файл не открыт для чтения или выходной файл не открыт для записи.
Неправильный адрес.
Неправильный или заблокированный дескриптор, или для in_fd недоступна операция типа mmap(2).
Неизвестная ошибка при чтении in_fd.
Не хватает памяти для чтения in_fd.

ВЕРСИИ

Вызов sendfile() впервые появился в Linux 2.2. Файл заголовков <sys/sendfile.h> появился в glibc 2.1.

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

Отсутствует в POSIX.1-2001 и других стандартах.

В других системах UNIX вызов sendfile() реализован с другими семантиками и прототипами. Не должен использоваться в переносимых программах.

ЗАМЕЧАНИЯ

Если вы планируете использовать sendfile() для отправки файлов через сокет TCP и вам нужно послать некоторые заголовочные данные перед содержимым файла, то обратите внимание на параметр TCP_CORK, описанный в tcp(7), он поможет минимизировать количество пакетов и оптимизировать производительность.

В Linux 2.4 и более ранних, значение out_fd может также указывать на обычный файл, и sendfile() изменяет текущее смещение этого файла.

Первоначальная версия Linux sendfile() не была приспособлена для работы с большими файловыми смещениями. В последствии в Linux 2.4 был добавлен вызов sendfile64() с более широким диапазоном значений аргумента offset. В glibc sendfile() представляет собой обёрточную функцию, которая делает незаметным разницу между версиями ядер.

Приложение может попытаться воспользоваться read(2)/write(2), если вызов sendfile() завершится с ошибкой EINVAL или ENOSYS.

Специальный вызов Linux splice(2) поддерживает пересылку данных между произвольными файлами (например, между парой сокетов).

СМОТРИТЕ ТАКЖЕ

mmap(2), open(2), socket(2), splice(2)

2011-09-14 Linux