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 байт. Заметим, что при успешном выполнении вызов sendfile() может записать меньше байт, чем запрашивалось; вызывающий должен быть готов повторить вызов, если останутся не отправленные байты. Также смотрите ЗАМЕЧАНИЯ.
В случае ошибки возвращается -1 и значение errno устанавливается соответствующим образом.
Вызов sendfile() впервые появился в Linux 2.2. Файл заголовков <sys/sendfile.h> появился в glibc 2.1.
Отсутствует в POSIX.1-2001 и других стандартах.
В других системах UNIX вызов sendfile() реализован с другими семантиками и прототипами. Не должен использоваться в переносимых программах.
Вызов sendfile() передаст не больше 0x7ffff000 (2 147 479 552) байт, возвращая число байт, переданных на самом деле (это утверждение справедливо как к 32-битным, так и к 64-битным системам).
Если вы планируете использовать sendfile() для отправки файлов через сокет TCP и вам нужно послать некоторые заголовочные данные перед содержимым файла, то обратите внимание на параметр TCP_CORK, описанный в tcp(7), он поможет минимизировать количество пакетов и оптимизировать производительность.
В Linux 2.4 и более ранних, значение out_fd может также указывать на обычный файл; эта возможность была удалена в ядрах Linux 2.6.x, но возвращена в 2.6.33.
Первоначальная версия Linux sendfile() не была приспособлена для работы с большими файловыми смещениями. В последствии в Linux 2.4 был добавлен вызов sendfile64() с более широким диапазоном значений аргумента offset. В glibc sendfile() представляет собой обёрточную функцию, которая делает незаметным разницу между версиями ядер.
Приложение может попытаться воспользоваться read(2)/write(2), если вызов sendfile() завершится с ошибкой EINVAL или ENOSYS.
Если out_fd ссылается на сокет или канал с поддержкой нулевого копирования, то вызывающие должны гарантировать, что переданные части файла, указываемого in_fd, останутся неизменёнными до тех пор, пока читающий на другом конце out_fd не закончит обрабатывать переданные данные.
Специальный вызов Linux splice(2) поддерживает пересылку данных между произвольными файловыми дескрипторами, представляющими сокеты (один или оба).
2017-09-15 | Linux |