103 votes

E/S tamponnées vs E/S non tamponnées

J'ai appris que, par défaut, les E/S dans les programmes sont mises en mémoire tampon, c'est-à-dire qu'elles sont servies depuis un stockage temporaire au programme demandeur.
Je comprends que la mise en mémoire tampon améliore les performances d'E/S (peut-être en réduisant les appels système).
Une explication à ce sujet serait également utile.
J'ai également vu des fonctions comme setvbuf en C pour activer/désactiver la mise en mémoire tampon.

Je voulais savoir dans quels cas on voudrait des E/S sans tampon et pourquoi ?

Merci

150voto

paxdiablo Points 341644

Vous voulez une sortie sans tampon chaque fois que vous voulez vous assurer que la sortie a été écrite avant de continuer. Un exemple est l'erreur standard sous une bibliothèque d'exécution C - elle est généralement non tamponnée par défaut. Comme les erreurs sont (espérons-le) peu fréquentes, vous voulez en être informé immédiatement. D'autre part, la sortie standard est simplement parce que l'on suppose qu'il y aura beaucoup plus de données qui passeront par là.

Un autre exemple est une bibliothèque de journalisation. Si vos messages de journalisation sont conservés dans des tampons au sein de votre processus, et que votre processus décharge le noyau, il y a de fortes chances que la sortie ne soit jamais écrite.

En outre, les appels système ne sont pas les seuls à être réduits au minimum, les entrées/sorties de disque le sont également. Disons qu'un programme lit un fichier un octet à la fois. Avec une entrée non tamponnée, vous irez sur le disque (relativement très lent) pour chaque octet, même si vous devez probablement lire un bloc entier de toute façon (le matériel du disque lui-même peut avoir des tampons, mais vous irez quand même sur le contrôleur du disque, ce qui sera plus lent que l'accès en mémoire).

Grâce à la mise en mémoire tampon, l'ensemble du bloc est lu dans la mémoire tampon en une seule fois, puis les octets individuels vous sont livrés à partir de la zone tampon (en mémoire, incroyablement rapide).

N'oubliez pas que la mise en mémoire tampon peut prendre plusieurs formes, comme dans l'exemple suivant :

+-------------------+-------------------+
| Process A         | Process B         |
+-------------------+-------------------+
| C runtime library | C runtime library | C RTL buffers
+-------------------+-------------------+
|               OS caches               | Operating system buffers
+---------------------------------------+
|      Disk controller hardware cache   | Disk hardware buffers
+---------------------------------------+
|                   Disk                |
+---------------------------------------+

0 votes

Le graphique est merveilleux. Une chose qui mérite d'être mentionnée est qu'un FILE (un flux) est complètement différent d'un tampon interne de l'objet fgets paramètre de tampon requis. Cela m'a perturbé pendant des heures avant que je n'écrive du code pour le comprendre. QAQ

45voto

Aaron Points 2456

Vous souhaitez une sortie sans tampon lorsque vous avez déjà une grande séquence d'octets prêts à être écrits sur le disque, et que vous souhaitez éviter une copie supplémentaire dans un second tampon au milieu.

Les flux de sortie tamponnés accumulent les résultats d'écriture dans un tampon intermédiaire, et ne les envoient au système de fichiers du système d'exploitation que lorsque suffisamment de données se sont accumulées (ou lorsque flush() est demandé). Ceci réduit le nombre d'appels au système de fichiers. Puisque les appels au système de fichiers peuvent être coûteux sur la plupart des plates-formes (comparés au memcpy court), la sortie tamponnée est un gain net lorsqu'on effectue un grand nombre de petites écritures. La sortie sans tampon est généralement meilleure lorsque vous avez déjà de grands tampons à envoyer -- copier vers un tampon intermédiaire ne réduira pas davantage le nombre d'appels au système d'exploitation, et introduit du travail supplémentaire.

La sortie non tamponnée a rien Cette fonctionnalité est fournie par flush(), et fonctionne à la fois sur les flux tamponnés et non tamponnés. Les écritures d'E/S sans tampon ne garantissent pas que les données ont atteint le disque physique -- le système de fichiers du système d'exploitation est libre de conserver indéfiniment une copie de vos données, sans jamais les écrire sur le disque, s'il le souhaite. Il n'est tenu de les livrer sur le disque que lorsque vous invoquez flush(). (Notez que close() appellera flush() en votre nom).

0 votes

Appel de la volonté flush() garantir qu'il est écrit sur le disque ? Je pensais que ça ne faisait que le transmettre à la mémoire tampon du disque.

2 votes

Vous devez O_SYNC pour garantir les écritures.

0 votes

Les entrées-sorties non tamponnées ne se soucient pas d'être écrites sur le disque. Pour winapi, vous appelez CreateFile avec FILE_FLAG_NO_BUFFERING et FILE_FLAG_WRITE_THROUGH pour vous assurer que les données vont directement dans la persistance après chaque écriture. Pour d'autres OS, je ne sais pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X