Scroll to navigation

READV(2) Podręcznik programisty Linuksa READV(2)

NAZWA

readv, writev, preadv, pwritev, preadv2, pwritev2 - czytanie lub zapisywanie danych do wielu buforów

SKŁADNIA

#include <sys/uio.h>
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
ssize_t preadv(int fd, const struct iovec *iov, int iovcnt,
               off_t offset);
ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt,
                off_t offset);
ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt,
                off_t offset, int flags);
ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt,
                 off_t offset, int flags);

Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):

preadv(), pwritev():
Od glibc 2.19:
_DEFAULT_SOURCE
Glibc 2.19 i wcześniejsze:
_BSD_SOURCE

OPIS

Wywołanie systemowe readv() czyta liczbę iovcnt bloków z pliku skojarzonego z deskryptorem pliku fd do wielu buforów opisanych przez iov ("rozrzucone wejście").

Funkcja writev() zapisuje co najwyżej iovcnt bloków opisanych przez iov do pliku skojarzonego z deskryptorem pliku fd ("zgromadzone wyjście").

Wskaźnik iov prowadzi do struktury iovec zdefiniowanej w pliku <sys/uio.h> następująco:


struct iovec {

void *iov_base; /* Adres początkowy */
size_t iov_len; /* Liczba bajtów do przeniesienia */ };

Wywołanie systemowe readv() działa tak samo jak read(2), z tą różnicą że wypełnianych jest wiele buforów.

Wywołanie systemowe writev() działa tak samo jak write(2), z tą różnicą że zapisywane dane pochodzą z wielu buforów.

Bufory są przetwarzane w porządku, w którym zostały wymienione w tablicy. Oznacza to, że readv() całkowicie zapełni iov[0] zanim przejdzie do iov[1] itd. (jeśli jest za mało danych, to nie wszystkie bufory w iov zostaną wypełnione). Podobnie writev zapisuje całkowicie zawartość iov[0], zanim przejdzie do iov[1], itd.

Transfery danych przeprowadzane przez readv() i writev() są atomowe: dane zapisywane przez writev() są zapisywane jako pojedynczy blok danych, niekolidujący z danymi zapisywanymi przez inne procesy (z jednym wyjątkiem, patrz pipe(7)). Analogicznie readv() gwarantuje przeczytanie sąsiadujących bloków danych, niezależnie od operacji odczytu przeprowadzanych przez inne wątki lub procesy mające deskryptory plików odnoszące się do tego samego otwartego pliku (patrz open(2)).

preadv() i pwritev()

Wywołanie systemowe preadv() łączy w sobie funkcjonalności dostarczane przez readv() i przez pread(2). Wykonuje to samo zadanie, co readv(), ale dodaje czwarty argument, offset, określający miejsce w pliku, w którym zostanie przeprowadzona operacja wejściowa.

Wywołanie systemowe pwritev() łączy w sobie funkcjonalności dostarczane przez writev() i przez pwrite(2). Wykonuje to samo zadanie, co writev, ale dodaje czwarty argument, offset, określający miejsce w pliku, w którym zostanie przeprowadzona operacja wyjściowa.

Opisywane wywołania systemowe nie zmieniają pozycji przesunięcia w pliku. Pliki wskazywane przez fd muszą pozwalać na swobodny dostęp (przeszukiwanie).

preadv2() i pwritev2()

Te wywołania systemowe są podobne do wywołań preadv() i pwritev(), lecz dodają piąty argument flags, modyfikujący zachowanie w zależności od wywołania.

W przeciwieństwie do preadv() i pwritev(), jeśli argument offset wynosi -1, to używane i aktualizowane jest przesunięcie bieżącego pliku.

Argument flags zawiera bitowe LUB z jednej lub więcej z następujących flag:

Provide a per-write equivalent of the O_DSYNC open(2) flag. This flag is meaningful only for pwritev2(), and its effect applies only to the data range written by the system call.
Odczyt/zapis o wysokim priorytecie. Pozwala blokowym systemom plików na odpytywanie urządzenia, co zapewnia niższe opóźnienia, lecz może wymagać dodatkowych zasobów (obecnie ta funkcja nadaje się do użycia wyłącznie, jeśli deskryptor pliku otwarto z flagą O_DIRECT).
Provide a per-write equivalent of the O_SYNC open(2) flag. This flag is meaningful only for pwritev2(), and its effect applies only to the data range written by the system call.
Do not wait for data which is not immediately available. If this flag is specified, the preadv2() system call will return instantly if it would have to read data from the backing storage or wait for a lock. If some data was successfully read, it will return the number of bytes read. If no bytes were read, it will return -1 and set errno to EAGAIN. Currently, this flag is meaningful only for preadv2().
Provide a per-write equivalent of the O_APPEND open(2) flag. This flag is meaningful only for pwritev2(), and its effect applies only to the data range written by the system call. The offset argument does not affect the write operation; the data is always appended to the end of the file. However, if the offset argument is -1, the current file offset is updated.

WARTOŚĆ ZWRACANA

Gdy się powiodą, funkcje readv(), preadv() i preadv2() zwracają liczbę przeczytanych bajtów, a funkcje writev(), pwritev() i pwritev2() zwracają liczbę bajtów zapisanych.

Proszę zauważyć, że nie jest błędem przesłanie mniejszej liczby bajtów niż żądano przez poprawne wywołanie (zob. read(2) i write(2)).

W razie wystąpienia błędu zwracane jest -1 i ustawiana jest odpowiednia wartość zmiennej errno.

BŁĘDY

Zwracane błędy są takie same, jak w przypadku funkcji read(2) i write(2). Ponadto preadv(), preadv2(), pwritev() i pwritev2() mogą także zwrócić błędy takie jak w przypadku lseek(2). Dodatkowo zdefiniowane są następujące błędy:

Suma wartości iov_len przekracza rozmiar ssize_t.
Liczba iovcnt wektorów jest mniejsza niż zero lub większa niż dopuszczalne maksimum.
Jako flags podano nieznaną flagę.

WERSJE

preadv() i pwritev() po raz pierwszy pojawiły się w Linuksie 2.6.30; wsparcie biblioteczne tych wywołań pojawiło się w glibc 2.10.

preadv2() i pwritev2() po raz pierwszy pojawiły się w Linuksie 4.6; wsparcie biblioteczne tych wywołań pojawiło się w glibc 2.26.

ZGODNE Z

readv(), writev(): POSIX.1-2001, POSIX.1-2008, 4.4BSD (wywołania te początkowo pojawiły się w BSD 4.2).

preadv(), pwritev(): niestandardowe, ale obecne także w nowoczesnych systemach BSD.

preadv2(), pwritev2(): niestandardowe rozszerzenie systemu Linux.

UWAGI

POSIX.1 pozwala w implementacji umieścić ograniczenie liczby argumentów, które mogą być przekazane w iov. Implementacja może rozgłosić ten limit definiując IOV_MAX w <limits.h> lub w czasie uruchomienia, zwracaną wartością z sysconf(_SC_IOV_MAX). Na współczesnych systemach Linux limit ten wynosi 1024. W czasach Linuksa 2.0 wynosił 16.

Różnice biblioteki C/jądra

Surowe wywołania systemowe preadv() i pwritev() mają sygnatury wywołań różniące się subtelnie od odpowiadających im w funkcji opakowującej biblioteki GNU C pokazanych w SKŁADNI. Ostatni argument offset, jest rozpakowany przez funkcję opakowującą na dwa argumenty wywołania systemowego:

unsigned long pos_l, unsigned long pos

Argumenty te zawierają 32 bitowy offset w kolejności odpowiednio, od najmniej i od najbardziej znaczącego bitu.

Historyczne różnice biblioteki C/jądra

Aby rozwiązać sytuację, gdy IOV_MAX było tak niskie we wczesnych wersjach Linuksa, funkcje opakowujące readv() i writev() wykonywały pewne dodatkowe działania po wykryciu, że odpowiednie wywołanie systemowe zakończyło się błędem z powodu przekroczenia limitu. W takim wypadku funkcja readv() biblioteki glibc przydzielała tymczasowy bufor, wystarczająco duży, by pomieścić wszystkie elementy określone przez iov, przekazywała ten bufor wywołaniu systemowemu read(2), kopiowała dane z bufora tymczasowego do lokalizacji określonych przez iov, a następnie zwalniała pamięć bufora. Funkcja glibc dla writev() wykonywała analogiczne zadanie, używając bufora tymczasowego i wywołania funkcji write(2).

Potrzeba tych dodatkowych działań funkcji opakowujących glibc przestała być potrzebna od Linuksa 2.2. Jednak glibc wciąż udostępniał to działanie do wersji 2.10. Poczynając od wersji 2.9 glibc, funkcje opakowujące wykonywały to działanie tylko jeśli biblioteka wykryła, że system działa pod kontrolą jądra Linux starszego niż 2.6.18 (wybór tej wersji jądra nie ma głębszej przyczyny). Od glibc 2.10 (wymagającej co najmniej Linuksa 2.6.32) funkcje opakowujące glibc bezpośrednio przywołują wywołania systemowe.

PRZYKŁADY

Następujący przykładowy kod pokazuje użycie funkcji writev():


char *str0 = "witaj ";
char *str1 = "świecie\n";
struct iovec iov[2];
ssize_t nwritten;
iov[0].iov_base = str0;
iov[0].iov_len = strlen(str0);
iov[1].iov_base = str1;
iov[1].iov_len = strlen(str1);
nwritten = writev(STDOUT_FILENO, iov, 2);

ZOBACZ TAKŻE

pread(2), read(2), write(2)

O STRONIE

Angielska wersja tej strony pochodzi z wydania 5.10 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów oraz najnowszą wersję oryginału można znaleźć pod adresem https://www.kernel.org/doc/man-pages/.

TŁUMACZENIE

Autorami polskiego tłumaczenia niniejszej strony podręcznika są: Robert Luberda <robert@debian.org> i 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 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.

21 grudnia 2020 r. Linux