splice(2) System Calls Manual splice(2) NAZWA splice - przenosi dane do/z potoku BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #define _GNU_SOURCE /* Zob. feature_test_macros(7) */ #define _FILE_OFFSET_BITS 64 #include ssize_t splice(int fd_in, off_t *_Nullable off_in, int fd_out, off_t *_Nullable off_out, size_t size, unsigned int flags); OPIS splice() przenosi dane pomiedzy dwoma deskryptorami plikow, bez kopiowania pomiedzy przestrzenia adresowa jadra i przestrzenia adresowa uzytkownika. Transferuje maksymalnie size bajtow z deskryptora pliku fd_in do deskryptora pliku fd_out, przy czym jeden z deskryptorow plikow musi odnosic sie do potoku. fd_in i off_in sa objete nastepujaca semantyka: o Jesli fd_in odnosi sie do potoku, to off_in musi wynosic NULL. o Jesli fd_in nie odnosi sie do potoku, a off_in wynosi NULL, to bajty sa odczytywane z fd_in poczawszy od przesuniecia pliku, a przesuniecie pliku jest odpowiednio dostosowywane. o Jesli fd_in nie odnosi sie do pliku, a off_in nie wynosi NULL, to off_in musi wskazywac na bufor, okreslajacy poczatkowe przesuniecie, od ktorego zostana odczytane bajty w fd_in; w tym przypadku przesuniecie pliku fd_in pozostaje bez zmian, w zamian odpowiednio dostosowywane jest przesuniecie, na ktore wskazuje off_in. Analogiczne stwierdzenia stosuja sie do fd_out i off_out. Argument flags jest maska bitowa tworzona jako suma logiczna (OR) zera lub wiekszej liczby nastepujacych wartosci: SPLICE_F_MOVE Probuje przesunac strony zamiast je kopiowac. Jest to tylko wskazowka dla jadra: strony wciaz moga byc skopiowane, jesli jadro nie moze przesunac stron z potoku lub jesli bufory potoku nie odnosza sie do pelnych stron. Pierwotna implementacja tego znacznika byla nieprawidlowa: z tego wzgledu poczawszy od Linuksa 2.6.21 nie odnosi on skutku (jednak wciaz jest dozwolony w wywolaniu do splice()); w przyszlosci moze byc przywrocona poprawna implementacja. SPLICE_F_NONBLOCK Nie blokuje wejscia/wyjscia. Operacje splice na potoku beda nieblokujace, jednak splice() wciaz moze zablokowac, poniewaz deskryptory plikow do/z ktorych nastepuje splice moga blokowac (chyba, ze maja one ustawiony znacznik O_NONBLOCK). SPLICE_F_MORE W kolejnym splice nadejdzie wiecej danych. Jest to przydatna wskazowka, gdy fd_out odnosi sie do gniazda (zob. tez opis MSG_MORE w send(2) oraz opis TCP_CORK w tcp(7)). SPLICE_F_GIFT Nieuzywane w splice(); zob. vmsplice(2). WARTOSC ZWRACANA Po pomyslnym zakonczeniu splice() zwraca liczbe bajtow przeniesionych do lub z potoku. Zwracana wartosc 0 oznacza koniec wejscia. Jesli fd_in odnosi sie do potoku, oznacza to, ze nie bylo danych do transferu, zatem blokowanie nie mialo sensu, poniewaz nie bylo zapisujacych do konca do zapisu potoku. W razie wystapienia bledu splice zwraca -1 i ustawia errno, wskazujac blad. BLEDY EAGAIN We flags podano SPLICE_F_NONBLOCK lub jeden z deskryptorow plikow oznaczono jako nieblokujacy (O_NONBLOCK), natomiast operacja spowodowalaby blokowanie. EBADF Jeden lub wiecej deskryptorow plikow nie jest prawidlowych lub nie maja prawidlowego trybu do odczytu i zapisu. EINVAL Docelowy system plikow nie obsluguje operacji splice. EINVAL Docelowy plik jest otwarty w trybie dopisywania. EINVAL Zaden z deskryptorow plikow nie odnosi sie do potoku. EINVAL Podano przesuniecie dla urzadzenia, ktore nie jest przewijalne (np. potok). EINVAL fd_in i fd_out odnosza sie do tego samego potoku. ENOMEM Brak pamieci. ESPIPE off_in albo off_out nie mialy wartosci NULL, a odpowiadajacy deskryptor pliku odnosil sie do potoku. STANDARDY Linux. HISTORIA Linux 2.6.17, glibc 2.5. W Linuksie 2.6.30 i wczesniejszych, dokladnie jeden z argumentow fd_in i fd_out musial byc potokiem. Od Linuksa 2.6.31 oba argumenty moga odnosic sie do potokow. UWAGI Trzy wywolania systemowe: splice(), vmsplice(2) i tee(2) zapewniaja programom w przestrzeni uzytkownika pelna kontrole nad pewnym buforem jadra, zaimplementowanym w jadrze uzywajac tego samego typu bufora, jaki jest uzywany dla potoku. Ogolnie, te wywolania systemowe spelniaja nastepujace role: splice() przenosi dane z bufora do dowolnego deskryptora pliku lub na odwrot, lub z jednego bufora do innego. tee(2) ,,kopiuje" dane z jednego bufora do drugiego. vmsplice(2) ,,kopiuje" dane z przestrzeni uzytkownika do bufora. Choc mowa tu o kopiowaniu, generalnie unika sie faktycznego kopiowania. Jadro dokonuje tego implementujac bufor potoku jako zbior wskaznikow, z licznikami odniesien, do stron pamieci jadra. Jadro tworzy ,,kopie" stron w buforze, tworzac nowe wskazniki (dla bufora wyjsciowego) odnoszace sie do stron oraz zwiekszajac liczniki odniesien do stron: kopiowane sa tylko wskazniki, a nie strony bufora. _FILE_OFFSET_BITS powinno byc zdefiniowane jako 64 w kodzie, ktory uzywa wartosci off_in lub off_out innych niz null lub takim, ktory przyjmuje adres splice, jesli kod ma byc przenosny na tradycyjne, 32-bitowe platformy x86 i ARM, w ktorych szerokosc off_t domyslnie wynosi 32 bity. PRZYKLADY Inny przyklad opisano w podreczniku tee(2). #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include int main(void) { int fd; int pfd[2]; off_t off; const char s[14] = "Witaj swiecie!"; fd = open("out", O_WRONLY | O_CREAT | O_EXCL, 0666); if (fd == -1) err(EXIT_FAILURE, "open"); if (pipe(pfd) == -1) err(EXIT_FAILURE, "pipe"); if (write(pfd[1], s, sizeof(s)) != sizeof(s)) err(EXIT_FAILURE, "write"); if (close(pfd[1]) == -1) err(EXIT_FAILURE, "close"); off = 10; if (splice(pfd[0], NULL, fd, &off, sizeof(s), 0) != sizeof(s)) err(EXIT_FAILURE, "splice"); if (close(pfd[0]) == -1) err(EXIT_FAILURE, "close"); printf("Nowy przesuniecie wynosi %jd\n", (intmax_t) off); if (close(fd) == -1) err(EXIT_FAILURE, "close"); exit(EXIT_SUCCESS); } ZOBACZ TAKZE copy_file_range(2), sendfile(2), tee(2), vmsplice(2), pipe(7) TLUMACZENIE Tlumaczenie niniejszej strony podrecznika: Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.15 17 maja 2025 r. splice(2)