Sie möchten eine ungepufferte Ausgabe, wenn Sie sicherstellen möchten, dass die Ausgabe geschrieben wurde, bevor Sie fortfahren. Ein Beispiel ist ein Standardfehler unter einer C-Laufzeitbibliothek - dieser ist normalerweise standardmäßig ungepuffert. Da Fehler (hoffentlich) selten sind, möchten Sie sie sofort kennen. Auf der anderen Seite, die Standardausgabe ist einfach gepuffert , weil es dort angenommen , durchläuft es weit mehr Daten sein wird.
Ein weiteres Beispiel ist eine Protokollierungsbibliothek. Wenn Ihre Protokollnachrichten in Puffern in Ihrem Prozess gespeichert sind und Ihr Prozess den Kern entleert, besteht eine sehr gute Chance, dass die Ausgabe niemals geschrieben wird.
Darüber hinaus werden nicht nur Systemaufrufe minimiert, sondern auch Festplatten-E / A. Angenommen, ein Programm liest eine Datei byteweise. Bei ungepufferter Eingabe gehen Sie für jedes Byte auf die (relativ sehr langsame) Festplatte, obwohl sie wahrscheinlich ohnehin einen ganzen Block einlesen muss (die Festplattenhardware selbst verfügt möglicherweise über Puffer, aber Sie gehen immer noch zum Festplattencontroller Dies wird langsamer sein als der In-Memory-Zugriff.
Durch das Puffern wird der gesamte Block sofort in den Puffer eingelesen, und die einzelnen Bytes werden Ihnen aus dem (speicherinternen, unglaublich schnellen) Pufferbereich zugestellt.
Beachten Sie, dass die Pufferung viele Formen annehmen kann, wie im folgenden Beispiel:
+-------------------+-------------------+
| 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 |
+---------------------------------------+
FILE
interne Puffer eines Objekts (eines Streams) vollständig von einemfgets
erforderlichen Pufferparameter unterscheidet. Das hat mich nur stundenlang verwirrt, bevor ich einen Code geschrieben habe, um es herauszufinden. QAQSie möchten eine ungepufferte Ausgabe, wenn Sie bereits eine große Folge von Bytes zum Schreiben auf die Festplatte bereit haben, und möchten eine zusätzliche Kopie in einen zweiten Puffer in der Mitte vermeiden .
Gepufferte Ausgabestreams sammeln Schreibergebnisse in einem Zwischenpuffer und senden sie nur dann an das Betriebssystem-Dateisystem, wenn sich genügend Daten angesammelt haben (oder
flush()
angefordert werden). Dies reduziert die Anzahl der Dateisystemaufrufe. Da Dateisystemaufrufe auf den meisten Plattformen teuer sein können (im Vergleich zu kurzenmemcpy
), ist die gepufferte Ausgabe ein Nettogewinn, wenn eine große Anzahl kleiner Schreibvorgänge ausgeführt wird. Die ungepufferte Ausgabe ist im Allgemeinen besser, wenn Sie bereits große Puffer zum Senden haben. Durch das Kopieren in einen Zwischenpuffer wird die Anzahl der Betriebssystemaufrufe nicht weiter reduziert, und es wird zusätzliche Arbeit eingeführt.Die ungepufferte Ausgabe hat nichts damit zu tun, dass Ihre Daten die Festplatte erreichen. Diese Funktionalität wird von
flush()
gepufferten und ungepufferten Streams bereitgestellt und funktioniert sowohl für gepufferte als auch für ungepufferte Streams. Ungepufferte E / A-Schreibvorgänge garantieren nicht, dass die Daten die physische Festplatte erreicht haben. Das Betriebssystem-Dateisystem kann eine Kopie Ihrer Daten unbegrenzt aufbewahren und sie niemals auf die Festplatte schreiben, wenn dies gewünscht wird. Es ist nur erforderlich, es beim Aufrufen auf die Festplatte zu übertragenflush()
. (Beachten Sie, dassclose()
inflush()
Ihrem Namen anrufen wird ).quelle
flush()
garantieren, dass er auf die Festplatte geschrieben wurde? Ich dachte, das würde es nur an den Puffer der Festplatte weitergeben.O_SYNC
sicherstellen, dass Schreibvorgänge garantiert werden.