Linux: Quand utiliser IO scatter / collecte (readv, writev) contre un grand tampon avec fread

Dans la dispersion et la collecte (c.-à-d. readv et writev ), Linux lit plusieurs tampons et écrit à partir de plusieurs tampons.

Si, par exemple, j’ai un vecteur de 3 tampons, je peux utiliser readv , OU je peux utiliser un seul tampon, qui est de taille combinée de 3 tampons et qui fait du fread .

Par conséquent, je suis confus: pour quels cas la dispersion / collecte devrait-elle être utilisée et quand un seul grand tampon devrait-il être utilisé?

La commodité principale offerte par readv , writev est:

  1. Il permet de travailler avec des blocs de données non contigus. En d’autres termes, les tampons ne doivent pas nécessairement faire partie d’un tableau, mais être alloués séparément.
  2. L’E / S est “atomique”. Si vous faites un writev , tous les éléments du vecteur seront écrits dans une opération contiguë, et les écritures effectuées par d’autres processus ne se produiront pas entre elles.

Par exemple, vos données sont naturellement segmentées et proviennent de différentes sources:

 struct foo *my_foo; struct bar *my_bar; struct baz *my_baz; my_foo = get_my_foo(); my_bar = get_my_bar(); my_baz = get_my_baz(); 

Maintenant, les trois «tampons» ne sont pas un gros bloc contigu. Mais vous voulez les écrire de manière contiguë dans un fichier, pour quelque raison que ce soit (par exemple, ce sont des champs dans un en-tête de fichier pour un format de fichier).

Si vous utilisez write vous devez choisir entre:

  1. Les copier dans un bloc de mémoire en utilisant, par exemple, memcpy (overhead), suivi d’un seul appel en write . Alors l’écriture sera atomique.
  2. Faire trois appels distincts pour write (overhead). En outre, les appels d’ write provenant d’autres processus peuvent s’intercaler entre ces écritures (non atomiques).

Si vous utilisez plutôt writev , tout va bien:

  1. Vous faites exactement un appel système et vous ne memcpy pas créer un seul tampon à partir des trois.
  2. En outre, les trois tampons sont écrits de manière atomique, comme un bloc écrit. c’est-à-dire que si d’autres processus écrivent aussi, alors ces écritures n’entreront pas entre les écritures des trois vecteurs.

Donc, vous feriez quelque chose comme:

 struct iovec iov[3]; iov[0].iov_base = my_foo; iov[0].iov_len = sizeof (struct foo); iov[1].iov_base = my_bar; iov[1].iov_len = sizeof (struct bar); iov[2].iov_base = my_baz; iov[2].iov_len = sizeof (struct baz); bytes_written = writev (fd, iov, 3); 

Sources:

  1. http://pubs.opengroup.org/onlinepubs/009604499/functions/writev.html
  2. http://linux.die.net/man/2/readv