2009-09-20 5 views
56

Ich erfuhr, dass standardmäßig I/O in Programmen gepuffert ist, d. H. Sie werden von einem temporären Speicher an das anfordernde Programm geliefert. Ich verstehe, dass das Puffern die E/A-Leistung verbessert (möglicherweise durch Reduzieren von Systemaufrufen). Ich habe Beispiele für das Deaktivieren der Pufferung gesehen, wie zB setvbuf in C. Was ist der Unterschied zwischen den beiden Modi und wann sollte man den anderen verwenden?Gepufferte vs ungepufferte IO

Antwort

90

Sie möchten eine ungepufferte Ausgabe, wenn Sie sicherstellen möchten, dass die Ausgabe geschrieben wurde, bevor Sie fortfahren. Ein Beispiel ist der Standardfehler unter einer C-Laufzeitbibliothek - dieser ist standardmäßig standardmäßig ungepuffert. Da Fehler (hoffentlich) selten sind, möchten Sie diese sofort kennen. Auf der anderen Seite ist die Standardausgabe gepuffert einfach weil es angenommen wird, dass es viel mehr Daten durch es gehen wird.

Ein anderes Beispiel ist eine Protokollierungsbibliothek. Wenn Ihre Protokollnachrichten in Puffern in Ihrem Prozess gespeichert werden und Ihr Prozess einen Core-Dump ablegt, besteht eine sehr gute Chance, dass die Ausgabe nie geschrieben wird.

Darüber hinaus werden nicht nur Systemaufrufe minimiert, sondern auch Festplatten-E/A. Nehmen wir an, ein Programm liest eine Datei ein Byte nach der anderen. Mit der ungepufferten Eingabe gehen Sie für jedes Byte auf die (relativ sehr langsame) Festplatte, obwohl sie wahrscheinlich sowieso einen ganzen Block einlesen muss (die Festplatten-Hardware selbst kann Puffer haben, aber Sie gehen immer noch zum Festplatten-Controller was langsamer als der Speicherzugriff sein wird).

Durch die Pufferung wird der gesamte Block sofort in den Puffer eingelesen, dann werden Ihnen die einzelnen Bytes aus dem (speicherinternen, unglaublich schnellen) Pufferbereich zugestellt.

Beachten Sie, dass Pufferung viele Formen, wie im folgenden Beispiel nehmen:

+-------------------+-------------------+ 
| 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    | 
+---------------------------------------+ 
21

Sie ungepufferten Ausgang wünschen, wenn Sie bereits große Folge von Bytes bereit halten auf Platte zu schreiben, und möchte Vermeiden Sie eine zusätzliche Kopie in einen zweiten Puffer in der Mitte.

Gepufferte Ausgabeströme akkumulieren Schreibergebnisse in einen Zwischenpuffer und senden sie nur dann an das Dateisystem des Betriebssystems, wenn genügend Daten angesammelt wurden (oder flush() angefordert wird). Dies reduziert die Anzahl der Dateisystemaufrufe. Da Dateisystemaufrufe auf den meisten Plattformen teuer sein können (im Vergleich zu einem kurzen Speicher), ist die gepufferte Ausgabe ein Nettogewinn, wenn eine große Anzahl kleiner Schreibvorgänge ausgeführt wird. Ungepufferte Ausgabe ist im Allgemeinen besser, wenn Sie bereits große Puffer zum Senden haben - das Kopieren in einen Zwischenpuffer verringert die Anzahl der Betriebssystemaufrufe nicht weiter und führt zu zusätzlicher Arbeit.

Unbuffered Ausgang hat nichts zu tun mit der Sicherstellung, dass Ihre Daten die Festplatte erreicht; Diese Funktionalität wird von flush() bereitgestellt und funktioniert sowohl bei gepufferten als auch bei ungepufferten Streams. Ungepufferte E/A-Schreibvorgänge garantieren nicht, dass die Daten die physische Festplatte erreicht haben - das Dateisystem des Betriebssystems ist frei, eine Kopie Ihrer Daten auf unbestimmte Zeit festzuhalten und sie niemals auf die Festplatte zu schreiben, wenn dies gewünscht wird. Es muss nur beim Aufruf von flush() auf den Datenträger geschrieben werden. (Beachten Sie, dass close() in Ihrem Namen flush() aufruft.

+0

Wird der Aufruf von 'flush()' garantieren, dass es auf die Festplatte geschrieben wird? Ich dachte, dass es nur an den Puffer der Platte weitergegeben wurde. – jrdioko

+2

Sie benötigen 'O_SYNC', um Schreibvorgänge zu garantieren. – moshbear