sendfile(2)

NAZWA
sendfile - przesyła dane pomiędzy deskryptorami plików

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <sys/sendfile.h>

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

OPIS
sendfile() kopiuje dane pomiędzy dwoma deskryptorami plików. Kopiowanie odbywa się wewnątrz jądra, dlatego sendfile() jest wydajniejsze niż połączenie read(2) z write(2), które wymagałoby przesłania danych do i z przestrzeni użytkownika.

in_fd powinien być deskryptorem pliku otwartym do odczytu, a out_fd powinien być deskryptorem otwartym do zapisu.

Jeśli offset nie wynosi NULL, to wskazuje on na zmienną przechowującą przesunięcie pliku, od którego sendfile() zacznie odczytywać dane z in_fd. Gdy sendfile() powróci, zmienna ta zostanie ustawiona na przesunięcie bajtu, który następuje po ostatnim odczytanym bajcie. Jeśli offset nie wynosi NULL, to sendfile() nie modyfikuje przesunięcia pliku in_fd; w innym przypadku przesunięcie pliku jest dostosowywane, aby uwzględnić liczbę bajtów odczytanych z in_fd.

Jeśli offset wynosi NULL, to dane będą odczytane z in_fd, począwszy od przesunięcia pliku, a przesunięcie pliku zostanie zaktualizowane przez to wywołanie.

count jest liczbą bajtów do skopiowania pomiędzy deskryptorami plików.

Argument in_fd musi odnosić się do pliku obsługującego operacje w stylu mmap(2) (tj. nie może być gniazdem). Od Linuksa 5.12 nie dotyczy to sytuacji, gdy out_fd jest potokiem; wówczas sendfile() upraszcza się do splice(2) i stosują się jego ograniczenia.

Przed Linuksem 2.6.33, out_fd musiał odnosić się do gniazda. Od Linuksa 2.6.33 może być to dowolny plik. Jeśli jest przewijalny, to sendfile() odpowiednio dostosowuje przesunięcie pliku.

WARTOŚĆ ZWRACANA
Jeśli przesłanie się powiodło, zwracana jest liczba bajtów zapisanych do out_fd. Proszę zauważyć, że pomyślne wywołanie do sendfile() może zapisać mniej bajtów niż zażądano; wywołujący powinien być przygotowany na ponowienie wywołania, jeśli wystąpiły niewysłane bajty. Zob. też UWAGI.

W razie wystąpienia błędu zwracane jest -1 i ustawiane errno wskazując błąd.

BŁĘDY

EAGAIN
    Wybrano nieblokujące wejście/wyjście za pomocą O_NONBLOCK, a zapis zablokowałby.

EBADF
    Plik wejściowy nie został otwarty do odczytu lub plik wyjściowy nie został otwarty do zapisu.

EFAULT
    Niepoprawny adres.

EINVAL
    Deskryptor nie jest prawidłowy lub zablokowany; albo operacja w stylu mmap(2) nie jest dostępna dla in_fd; albo count jest ujemne.

EINVAL
    out_fd ma ustawiony znacznik O_APPEND. Obecnie nie jest to obsługiwane przez sendfile().

EIO Nieokreślony błąd przy odczycie z in_fd.

ENOMEM
    Zabrakło pamięci do odczytu z in_fd.

EOVERFLOW
    count jest zbyt duże, operacja spowodowałaby przekroczenie maksymalnego rozmiaru pliku wejściowego lub pliku wyjściowego.

ESPIPE
    offset nie wynosi NULL, lecz plik wejściowy nie jest przewijalny.

WERSJE
Inne systemy uniksowe implementują sendfile() z różnym zachowaniem i prototypami. Nie należy stosować tego wywołania w przenośnym programach.

STANDARDY
Brak.

HISTORIA
Linux 2.2, glibc 2.1.

W Linuksie 2.4 i wcześniejszych, out_fd mógł odnosić się także do zwykłego pliku; ta możliwość zniknęła w serii jąder Linux 2.6.x, lecz przywrócono ją w Linuksie 2.6.33.

Pierwotne, linuksowe wywołanie systemowe sendfile() nie było zaprojektowane do obsługi dużych przesunięć plików. Z tego względu w Linuksie 2.4 dodano sendfile64(), z szerszym typem argumentu offset. Funkcja opakowująca sendfile() z glibc radzi sobie z różnicami w jądrze w sposób transparentny.

UWAGI
sendfile() dokona transferu co najwyżej 0x7ffff000 (2 147 479 552) bajtów, zwracając liczbę bajtów faktycznie przesłanych (jest to prawdziwe zarówno dla systemów 32 jak i 64-bitowych).

Jeśli planuje się używać sendfile() do wysyłania plików do gniazda TCP, lecz przed zawartością pliku trzeba dołączyć jakieś dane nagłówka, przydatne będzie korzystanie z opcji TCP_CORK, opisanej w podręczniku tcp(7), w celu ograniczenia liczby pakietów i poprawienia wydajności.

Aplikacje mogą uznać za stosowne awaryjnie korzystanie z read(2) i write(2) w przypadku, gdy sendfile() zawiedzie z błędem EINVAL lub ENOSYS.

Jeśli out_fd odnosi się do gniazda lub potoku z obsługą zero-copy, wywołujący muszą upewnić się, że przesyłane części pliku, do których odnosi się in_fd, pozostaną niezmodyfikowane do momentu skonsumowania przesłanych danych przez odczytującego na drugim końcu out_fd.

Typowo linuksowe wywołanie splice(2) obsługuje przesyłanie danych pomiędzy dwoma dowolnymi deskryptorami plików, pod warunkiem, że jeden (lub obydwa) z nich jest potokiem.

ZOBACZ TAKŻE
copy_file_range(2), mmap(2), open(2), socket(2), splice(2)

TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 (https://www.gnu.org/licenses/gpl-3.0.html) lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.