READV(2) Manuale del programmatore di Linux READV(2)

readv, writev, preadv, pwritev, preadv2, pwritev2 - leggono o scrivono dati in buffer multipli

#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);
Macro per test di funzionalità per glibc (vedere feature_test_macros(7)):

preadv(), pwritev():


A partire da glibc 2.19:
_DEFAULT_SOURCE
Glibc 2.19 e precedenti:
_BSD_SOURCE

La chiamata di sistema readv() legge i buffer iovcnt dal file associato al descrittore di file fd nei buffer descritti da iov ("scatter input").

La chiamata di sistema writev() scrive i buffer di dati iovcnt descritti da iov nel file associato al descrittore di file fd ("gather output").

Il puntatore iov punta a un array di strutture iovec, definite in <sys/uio.h> come:


struct iovec {

void *iov_base; /* Indirizzo di partenza */
size_t iov_len; /* Numero di byte da trasferire */ };

La chiamata di sistema readv() funziona esattamente come read(2) tranne per il fatto che i buffer multipli sono riempiti.

La chiamata di sistema writev() funziona esattamente come write(2) tranne per il fatto che i buffer multipli sono svuotati.

I buffer sono elaborati in ordine di array. Ciò significa che readv() riempie completamente iov[0] prima di procedere a iov[1], e così via. (Se ci sono dati insufficienti allora non tutti i buffer puntati da iov possono essere riempiti) Similarmente, writev() estrae l'intero contenuto di iov[0] prima di procedere a iov[1], e così via.

The data transfers performed by readv() and writev() are atomic: the data written by writev() is written as a single block that is not intermingled with output from writes in other processes; analogously, readv() is guaranteed to read a contiguous block of data from the file, regardless of read operations performed in other threads or processes that have file descriptors referring to the same open file description (see open(2)).

La chiamata di sistema preadv() combina le funzionalità di readv() e di pread(2). Realizza lo stesso compito di readv(), ma aggiunge un quarto argomento, offset, che specifica la posizione nel file (offset) alla quale dev'essere effettuata l'operazione di input.

La chiamata di sistema pwritev() combina le funzionalità di writev() e di pwrite(2). Realizza lo stesso compito di writev(), ma aggiunge un quarto argomento, offset, che specifica la posizione nel file (offset) alla quale dev'essere effettuata l'operazione di input.

L'offset nel file non viene modificato da queste chiamate di sistema. Il file al quale fa riferimento fd deve poter permettere il posizionamento a un offset.

Queste chiamate di sistema sono simili alle chiamate preadv() e pwritev(), ma aggiungono un quinto argomento, flags, che modifica il comportamento a seconda del tipo di chiamata.

A differenza di preadv() e pwritev(), se l'argomento offset è -1, viene usato e aggiornato l'offset del file corrente.

L'argomento flags contiene un OR binario di zero o più dei seguenti flag:

Equivale a richiedere a livello di una singola scrittura la funzione richiesta dal flag O_DSYNC di open(2). Questo flag è significativo solo per pwritev2(), e il suo risultato si applica solo all'intervallo di dati scritto dalla chiamata di sistema.
Lettura/scrittura ad alta priorità. Permette ai filesystem basati su blocchi di usare la funzione di polling (interrogazione periodica) del dispositivo, il che permette di abbreviare il periodo di latenza, ma può implicare il consumo di ulteriori risorse. (Attualmente, questa funzionalità è usabile solo su un descrittore di fileaperto usando il flag O_DIRECT.)
Costituisce un equivalente per ogni singola scrittura (per-write) del flag O_SYNC di open(2). Questo flag è significativo solo per pwritev2(), e il suo risultato si applica solo all'intervallo di dati scritto dalla chiamata di sistema.
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 (but see BUGS). Currently, this flag is meaningful only for preadv2().
Costituisce un equivalente per ogni singola scrittura (per-write) del flag O_APPEND open(2) flag. Questo flag è significativo solo per pwritev2(), e il suo risultato si applica solo all'intervallo di dati scritto dalla chiamata di sistema. L'argomento offset non influisce sull'operazione di scrittura; i dati sono sempre accodati alla fine del file. Comunque, se l'argomento offset è -1, si usa e si aggiorna il file all'offset corrente.

In caso di successo, readv(), preadv() e preadv2() restituiscono il numero di byte letti; writev(), pwritev() e pwritev2() restituiscono il numero di byte scritti.

Si noti che non è un errore per una chiamata andata a buon fine trasferire meno byte di quelli richiesti (si veda read(2) e write(2)).

In caso di errore viene restituito -1 , e errno è impostato per indicare l'errore.

Gli errori sono gli stessi di read(2) e write(2). Per di più, preadv(), preadv2(), pwritev(), e pwritev2() possono anche non andare a buon fine per le stesse ragioni di lseek(2). Inoltre sono definiti i seguenti errori:

La somma dei valori iov_len supera un valore ssize_t.
Il vettore conteggio, iovcnt, è minore di zero o maggiore del massimo permesso.
Un flag sconosciuto è specificato in flags.

preadv() e pwritev() sono apparse per la prima volta in Linux 2.6.30; il supporto alla libreria è stato aggiunto in glibc 2.10.

preadv2() e pwritev2() sono apparse per la prima volta in Linux 4.6. Il supporto alla libreria è stato aggiunto in glibc 2.26.

readv(), writev(): POSIX.1-2001, POSIX.1-2008, 4.4BSD (queste chiamate di sistema sono apparse per la prima volta in 4.2BSD).

preadv(), pwritev(): non standard, però presente anche nei sistemi BSD moderni.

preadv2(), pwritev2(): Estensione Linux non standard.

POSIX.1 permette un'implementazione per porre un limite al numero di elementi che possono essere passati in iov. Un'implementazione può pubblicizzare i suoi limiti definendo IOV_MAX in <limits.h> o in run time attraverso il valore restituito da sysconf(_SC_IOV_MAX). Sui sistemi Linux moderni, il limite è 1024, prima di Linux 2.0 questo limite era 16.

Le chiamate di sistema dirette preadv() e pwritev() hanno firme che differiscono leggermente da quelle delle corrispondenti funzioni wrapper della libreria GNU C viste nella SINTASSI. L'argomento finale, offset, è spacchettato dalle funzioni wrapper in due argomenti nelle chiamate di sistema:

unsigned long pos_l, unsigned long pos

Questi argomenti contengono, rispettivamente, i 32 bit meno significativi e i 32 bit più significativi di offset.

Per affrontare il fatto che IOV_MAX era così basso nelle prime versioni di Linux, le funzioni wrapper di glibc per readv() e writev() facevano un lavoro aggiuntivo se rilevavano che la sottostante chiamata di sistema al kernel falliva perché era stato superato questo limite. Nel caso di readv() la funzione wrapper allocava un buffer temporaneo abbastanza grande per tutti gli elementi specificati da iov, passava questo buffer in una chiamata a read(2), copiava i dati dal buffer alle posizioni specificate dai campi iov_base degli elementi di iov, e infine liberava il buffer. La funzione wrapper per writev() eseguiva l'attività analoga usando un buffer temporaneo e una chiamata a write(2).

La necessità di questo sforzo aggiuntivo nelle funzioni wrappr glibc si rilevò con le versioni di Linux 2.2 e superiori. Comunque, glibc continuò con questo comportamento fino alla versione 2.10. A partire da glibc versione 2.9, le funzioni wrapper prevedono questo comportamento solo se la libreria rileva che il sistema sta eseguendo un kernel Linux più vecchio della versione 2.6.18 (unna versione del kernel scelta arbitrariamente). E da glibc 2.20 (che richiede una versione del kernel Linux superiore alla 2.6.32), le funzioni wrapper di glibc invocano sempre le chiamate di sistema direttamente.

Linux 5.9 and 5.10 have a bug where preadv2() with the RWF_NOWAIT flag may return 0 even when not at end of file.

Il seguente codice di esempio mostra l'uso di writev():


char *str0 = "hello ";
char *str1 = "world\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);

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

Questa pagina fa parte del rilascio 5.13 del progetto Linux man-pages. Una descrizione del progetto, le istruzioni per la segnalazione degli errori, e l'ultima versione di questa pagina si trovano su https://www.kernel.org/doc/man-pages/.

La traduzione italiana di questa pagina di manuale è stata creata da Giulio Daprelà <giulio@pluto.it> e Marco Curreli <marcocurreli@tiscali.it>

Questa traduzione è documentazione libera; leggere la GNU General Public License Versione 3 o successiva per le condizioni di copyright. Non ci assumiamo alcuna responsabilità.

Per segnalare errori nella traduzione di questa pagina di manuale inviare un messaggio a pluto-ildp@lists.pluto.it.

27 agosto 2021 Linux