read(2)

NOM
readv, writev, preadv, pwritev, preadv2, pwritev2 - Lire ou écrire des données dans plusieurs tampons

BIBLIOTHÈQUE
Bibliothèque C standard (libc, -lc)

SYNOPSIS
#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);

    Exigences de macros de test de fonctionnalités pour la glibc (consulter feature_test_macros(7)) :

preadv(), pwritev() :
    Depuis la glibc 2.19 :
        _DEFAULT_SOURCE
    glibc 2.19 et antérieures :
        _BSD_SOURCE

DESCRIPTION
L'appel système readv() lit iovcnt tampons depuis le fichier associé au descripteur de fichier fd dans les tampons décrits par iov.(« scatter input »)

L'appel système writev() écrit au plus iovcnt tampons de données décrits par iov dans le fichier associé au descripteur fd (« gather output »).

Le pointeur iov pointe vers un tableau de structures iovec, définies dans iovec(3type)

L'appel système readv() travaille comme read(2) sauf que plusieurs tampons sont remplis.

L'appel système writev() travaille comme write(2) sauf que plusieurs tampons sont écrits.

Les tampons sont considérés dans l'ordre du tableau. Cela signifie que readv() remplit iov[0] complètement avant d'en arriver à iov[1], et ainsi de suite. (S'il n'y a pas assez de données, tous les tampons pointés par iov ne seront pas forcément remplis.) De même, writev() écrit tout le contenu de iov[0] avant de considérer iov[1] et ainsi de suite.

Les transferts de données effectués par readv() et writev() sont atomiques : les données écrites par writev() sont écrites d'un bloc qui n'est pas interrompu par des écritures venant d'autres processus ; de façon similaire, readv() a la garantie de lire un bloc contigu de données depuis le fichier, quelles que soient les opérations de lecture effectuées par d'autres threads ou processus qui ont des descripteurs de fichier correspondant à la même description de fichier ouvert (consultez open(2)).

  preadv() et pwritev()
L'appel système preadv() combine les fonctionnalités de readv() et pread(2). Il effectue la même tâche que readv(), mais ajoute un quatrième paramètre, offset, qui indique la position dans le fichier à partir de laquelle l'opération d'entrée doit être effectuée.

L'appel système pwritev() combine les fonctionnalités de writev() et pwrite(2). Il effectue la même tâche que writev(), mais ajoute un quatrième paramètre, offset, qui indique la position dans le fichier à partir de laquelle l'opération de sortie doit être effectuée.

La position dans le fichier n'est pas modifiée par ces appels système. Le fichier décrit par fd doit permettre le positionnement.

  preadv2() et pwritev2()
Ces appels système sont identiques aux appels preadv() et pwritev() mais ils ajoutent un cinquième paramètre (flags) qui change le comportement sur la base de chaque appel.

Contrairement à preadv() et pwritev(), si le paramètre offset est -1, la tête de lecture du fichier actuel est utilisée et mise à jour.

L'argument flags est un opérateur OU binaire contenant zéro ou plusieurs des attributs suivants :

RWF_DSYNC (depuis Linux 4.7)
    Fournir un équivalent par écriture à l'attribut O_DSYNC d'open(2). Cet attribut n'a de sens que pour pwritev2() et son effet ne vaut que pour la plage de données écrite par l'appel système.

RWF_HIPRI (depuis Linux 4.6)
    Lecture/écriture haute priorité. Cela permet à des systèmes de fichiers fondés sur les blocs d'utiliser la scrutation du périphérique, ce qui donne moins de latence mais peut coûter plus de ressources (actuellement, cette fonctionnalité n'est utilisable que sur un descripteur de fichier ouvert avec l'attribut O_DIRECT).

RWF_SYNC (depuis Linux 4.7)
    Fournir un équivalent par écriture de l'attribut O_SYNC d'open(2). Cet attribut n'a de sens que pour pwritev2() et ses effets ne valent que pour la plage de données écrite avec cet appel système.

RWF_NOWAIT (depuis Linux 4.14)
    Ne pas attendre les données qui ne sont pas immédiatement disponibles. Si cet attribut est indiqué, l'appel système preadv2() renverra quelque chose instantanément s'il doit lire des données provenant d'un stockage de cache ou attendre un verrou. Si des données ont été lues avec succès, il renverra le nombre d'octets lus. Si aucun octet n'est lu, il renverra -1 et positionnera errno sur EAGAIN (mais consultez BUGS). Actuellement, cet attribut n'a de sens que pour preadv2().

RWF_APPEND (depuis Linux 4.16)
    Fournir un équivalent par écriture de l'attribut O_APPEND d'open(2). Cet attribut n'a de sens que pour pwritev2 et ses effets ne valent que pour la plage de données écrite par cet appel système. Le paramètre offset n’affecte pas l'opération d'écriture ; les données vont toujours à la fin du fichier. Cependant, si le paramètre offset est -1, la tête de lecture du fichier actuel est mise à jour.

RWF_NOAPPEND (since Linux 6.9)
    Do not honor the O_APPEND open(2) flag. This flag is meaningful only for pwritev2(). Historically, Linux honored O_APPEND flag if set and ignored the offset argument, which is a bug. For pwritev2(), the offset argument is honored as expected if RWF_NOAPPEND flag is set, the same as if O_APPEND flag were not set.

RWF_ATOMIC (since Linux 6.11)
    Requires that writes to regular files in block-based filesystems be issued with torn-write protection. Torn-write protection means that for a power or any other hardware failure, all or none of the data from the write will be stored, but never a mix of old and new data. This flag is meaningful only for pwritev2(), and its effect applies only to the data range written by the system call. The total write length must be power-of-2 and must be sized in the range [stx_atomic_write_unit_min, stx_atomic_write_unit_max]. The write must be at a naturally-aligned offset within the file with respect to the total write length. For example, a write of length 32KiB at a file offset of 32KiB is permitted, however a write of length 32KiB at a file offset of 48KiB is not permitted. The upper limit of iovcnt for pwritev2() is given by the value in stx_atomic_write_segments_max. Torn-write protection only works with O_DIRECT flag, i.e. buffered writes are not supported. To guarantee consistency from the write between a file's in-core state with the storage device, O_SYNC or O_DSYNC must be specified for open(2). The same synchronized I/O guarantees as described in open(2) are provided when these flags or their equivalent flags and system calls are used (e.g., if RWF_SYNC is specified for pwritev2()).

VALEUR RENVOYÉE
S'ils réussissent, readv(), preadv() et preadv2() renvoient le nombre d'octets lus ; writev, pwritev() et pwritev2() renvoient le nombre d'octets écrits.

Remarquez que le fait de transférer moins d'octets que deux demandés (voir read(2) et write(2)) ne constitue pas une erreur empêchant le succès de l'appel.

En cas d'erreur, la valeur de retour est -1 et errno est définie pour préciser l'erreur.

ERREURS
Les erreurs sont comme celles indiquées pour read(2) et write(2). En outre, preadv(), preadv2() et pwritev() peuvent aussi échouer pour les mêmes raisons que lseek(2). De plus, les erreurs suivantes peuvent survenir :

EINVAL
    La somme des valeurs iov_len déborde une valeur ssize_t.

EINVAL
    If RWF_ATOMIC is specified, the combination of the sum of the iov_len values and the offset value does not comply with the length and offset torn-write protection rules.

EINVAL
    The vector count, iovcnt, is less than zero or greater than the permitted maximum. If RWF_ATOMIC is specified, this maximum is given by the stx_atomic_write_segments_max value from statx.

EOPNOTSUPP
    Un drapeau inconnu est indiqué dans flags.

VERSIONS

  Différences entre bibliothèque C et noyau
Les appels système preadv() et pwritev() bruts ont une signature d'appel différant légèrement de celle des fonctions d'enveloppe de la bibliothèque C présentées dans le SYNOPSIS. Le paramètre offset final est dépaqueté par les fonctions d'enveloppe sous la forme de deux paramètres des appels système :

unsigned long pos_l, unsigned long pos

Ces paramètres contiennent respectivement les 32 bits d'ordre bas et haut de l'offset.

STANDARDS

readv()
writev()
    POSIX.1-2008.

preadv()
pwritev()
    BSD.

preadv2()
pwritev2()
    Linux.

HISTORIQUE

readv()
writev()
    POSIX.1-2001, 4.4BSD (apparu dans 4.2BSD).

preadv(), pwritev() : Linux 2.6.30, glibc 2.10.

preadv2(), pwritev2() : Linux 4.6, glibc 2.26.

  Différence historique entre la bibliothèque C et le noyau
Pour gérer le fait que IOV_MAX était trop bas sur les premières versions de Linux, les fonctions d'enveloppe de la glibc pour readv() et writev() effectuaient un travail supplémentaire si elles détectaient que les appels système du noyau sous-jacents échouaient à cause d'un dépassement de la limite. Pour readv(), la fonction d'enveloppe allouait un tampon temporaire assez grand pour tous les éléments de iov, passait ce tampon dans un appel read(2), copiait les données du tampon vers les emplacements indiqués par le champ iov_base des éléments de iov, puis libérait le tampon. La fonction d'enveloppe de writev() faisait la même chose avec un tampon temporaire et un appel à write(2).

La nécessité d'un tel effort supplémentaire par les fonctions d'enveloppe de la glibc a disparu avec Linux 2.2 et ultérieurs. Cependant la glibc a continué à fournir ce comportement jusqu'à la glibs 2.10. À partir de la version 2.9 de la glibc, les fonctions d'enveloppe ne fournissent ce comportement que si la bibliothèque détecte que le système a un noyau Linux plus ancien que Linux 2.6.18 (une version du noyau sélectionnée à votre guise). Depuis la glibc 2.20 (qui nécessite au minimum Linux 2.6.32), les fonctions d'enveloppe de la glibc appellent simplement les appels système dans tous les cas.

NOTES
POSIX.1 autorise une implémentation à poser une limite au nombre d'éléments qui peuvent être placés dans iov. Une implémentation peut indiquer cette limite en définissant IOV_MAX dans <limits.h> ou pendant l'exécution à l'aide d'un code de retour issu de sysconf(_SC_IOV_MAX). Sur les systèmes Linux modernes, la limite est de 1024. À l'époque de Linux 2.0, la limite était de 16.

BOGUES
Linux 5.9 et Linux 5.10 contiennent un bogue dans lequel preadv2() avec l'attribut RWF_NOWAIT peut renvoyer 0 même quand la fin du fichier n'est pas atteinte.

EXEMPLES
Le segment de code suivant donne un exemple d'utilisation de writev() :

    char          *str0 = "hello ";
    char          *str1 = "world\n";
    ssize_t       nwritten;
    struct iovec  iov[2];

    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);

VOIR AUSSI
pread(2), read(2), write(2)

TRADUCTION
La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org>, Frédéric Hantrais <fhantrais@gmail.com> et Jean-Philippe MENGUAL <jpmengual@debian.org>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 (https://www.gnu.org/licenses/gpl-3.0.html) concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.