splot (wywołanie systemowe) - splice (system call)
splice () tospecyficzne dla Linuksa wywołanie systemowe, które przenosi dane między deskryptorem pliku a potokiem bez podróży w obie strony do przestrzeni użytkownika. Powiązane wywołanie systemowe vmsplice () przenosi lub kopiuje dane między potokiem a przestrzenią użytkownika. W idealnym przypadku splice i vmsplice działają na zasadzie ponownego mapowania stron i nie kopiują w rzeczywistości żadnych danych, co może poprawićwydajność operacji we / wy . Ponieważ adresy liniowe niekoniecznie odpowiadają ciągłym adresom fizycznym, może to nie być możliwe we wszystkich przypadkach i dla wszystkich kombinacji sprzętowych.
Praca
Za pomocą metody splice () można przenosić dane z jednego deskryptora pliku do innego bez przenoszenia kopii z przestrzeni użytkownika do jądra, co jest zwykle wymagane do wymuszenia bezpieczeństwa systemu, a także do utrzymania prostego interfejsu dla procesów do odczytu i zapisu plików. splice () działa przy użyciu bufora potoku . Bufor potoku to wbudowany w jądro bufor pamięci, który jest nieprzezroczysty dla procesu w przestrzeni użytkownika. Proces użytkownika może podzielić zawartość pliku źródłowego w tym buforze potoku, a następnie podzielić bufor potoku na plik docelowy, a wszystko to bez przenoszenia danych w przestrzeni użytkownika.
Linus Torvalds opisał metodę splice () w e-mailu z 2006 roku, dołączonym do artykułu KernelTrap .
Pochodzenie
Linux realizacja splice zapożycza pomysły od pierwotnej propozycji, których autorem jest Larry McVoy w 1998 sklejenia wywołań systemowych pierwszy pojawił się w Linux kernel w wersji 2.6.17 i zostały napisane przez Jensa Axboe .
Prototyp
ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
Niektóre interesujące stałe to:
/* Splice flags (not laid down in stone yet). */
#ifndef SPLICE_F_MOVE
#define SPLICE_F_MOVE 0x01
#endif
#ifndef SPLICE_F_NONBLOCK
#define SPLICE_F_NONBLOCK 0x02
#endif
#ifndef SPLICE_F_MORE
#define SPLICE_F_MORE 0x04
#endif
#ifndef SPLICE_F_GIFT
#define SPLICE_F_GIFT 0x08
#endif
Przykład
Oto przykład splotu w akcji:
/* Transfer from disk to a log. */
int log_blocks (struct log_handle * handle, int fd, loff_t offset, size_t size)
{
int filedes [2];
int ret;
size_t to_write = size;
ret = pipe (filedes);
if (ret < 0)
goto out;
/* splice the file into the pipe (data in kernel memory). */
while (to_write > 0) {
ret = splice (fd, &offset, filedes [1], NULL, to_write,
SPLICE_F_MORE | SPLICE_F_MOVE);
if (ret < 0)
goto pipe;
else
to_write -= ret;
}
to_write = size;
/* splice the data in the pipe (in kernel memory) into the file. */
while (to_write > 0) {
ret = splice (filedes [0], NULL, handle->fd,
&(handle->fd_offset), to_write,
SPLICE_F_MORE | SPLICE_F_MOVE);
if (ret < 0)
goto pipe;
else
to_write -= ret;
}
pipe:
close (filedes [0]);
close (filedes [1]);
out:
if (ret < 0)
return -errno;
return 0;
}
Uzupełniające wywołania systemowe
splice () jest jednym z trzech wywołań systemowych, które uzupełniają architekturę splice () . vmsplice () może mapować obszar danych aplikacji na potok (lub odwrotnie), umożliwiając w ten sposób transfery między potokami a pamięcią użytkownika, gdzie sys_splice () przesyła między deskryptorem pliku a potokiem. tee () to ostatnia część trylogii. Dubluje jedną rurę do drugiej, umożliwiając rozwidlenia w sposobie łączenia aplikacji z rurami.
Wymagania
Używając splice () z gniazdami, kontroler sieciowy (NIC) powinien obsługiwać DMA, w przeciwnym razie metoda splice () nie zapewni znacznej poprawy wydajności. Powodem tego jest to, że każda strona potoku zapełni się po prostu do rozmiaru ramki (1460 bajtów z dostępnych 4096 bajtów na stronę).
Nie wszystkie typy systemów plików obsługują splice () . Ponadto gniazda AF_UNIX nie obsługują metody splice () .
Zobacz też
Bibliografia
Linki zewnętrzne
- Jądro Linuksa 2.6.17 (kernelnewbies.org)
- Dwa nowe wywołania systemowe: splice () i sync_file_range () ( LWN.net )
- Niektóre nowe wywołania systemowe (LWN.net)