Chcesz mieć niebuforowane dane wyjściowe, gdy chcesz mieć pewność, że dane wyjściowe zostały zapisane przed kontynuowaniem. Jednym z przykładów jest błąd standardowy w bibliotece wykonawczej C - zwykle jest on domyślnie niebuforowany. Ponieważ błędy są (miejmy nadzieję) rzadkie, chcesz się o nich natychmiast dowiedzieć. Z drugiej strony standardowe wyjście jest buforowane po prostu dlatego, że zakłada się, że będzie przez nie przechodziło znacznie więcej danych.
Innym przykładem jest biblioteka rejestrowania. Jeśli komunikaty dziennika są przechowywane w buforach procesu, a proces zrzuca jądro, istnieje bardzo duża szansa, że dane wyjściowe nigdy nie zostaną zapisane.
Ponadto zminimalizowane są nie tylko wywołania systemowe, ale także operacje wejścia / wyjścia dysku. Powiedzmy, że program czyta plik po jednym bajcie na raz. Z niebuforowanym wejściem wyjdziesz na (stosunkowo bardzo wolny) dysk dla każdego bajtu, mimo że prawdopodobnie i tak musi on odczytać cały blok (sam sprzęt dyskowy może mieć bufory, ale nadal wychodzisz do kontrolera dysku co będzie wolniejsze niż dostęp do pamięci).
Dzięki buforowaniu cały blok jest od razu wczytywany do bufora, a następnie poszczególne bajty są dostarczane z (niewiarygodnie szybkiego) obszaru bufora.
Pamiętaj, że buforowanie może przybierać różne formy, na przykład w poniższym przykładzie:
+-------------------+-------------------+
| 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
wewnętrzny bufor obiektu (strumienia) jest zupełnie inny niżfgets
wymagany parametr bufora. To tylko zdezorientowało mnie na wiele godzin, zanim napisałem kod, aby to rozgryźć. QAQPotrzebujesz niebuforowanego wyjścia, gdy masz już dużą sekwencję bajtów gotowych do zapisu na dysku i chcesz uniknąć dodatkowej kopii w drugim buforze w środku.
Buforowane strumienie wyjściowe będą gromadzić wyniki zapisu w buforze pośrednim, wysyłając je do systemu plików systemu operacyjnego tylko wtedy, gdy zgromadzi się wystarczająca ilość danych (lub
flush()
zostanie zażądana). Zmniejsza to liczbę wywołań systemu plików. Ponieważ wywołania systemu plików mogą być drogie na większości platform (w porównaniu do krótkichmemcpy
), buforowane wyjście jest wygraną netto przy wykonywaniu dużej liczby małych zapisów. Wyjście niebuforowane jest generalnie lepsze, gdy masz już duże bufory do wysłania - kopiowanie do bufora pośredniego nie zmniejszy dalej liczby wywołań systemu operacyjnego i wprowadza dodatkową pracę.Wyjście niebuforowane nie ma nic wspólnego z zapewnieniem, że dane dotrą na dysk; ta funkcjonalność jest zapewniana przez
flush()
buforowane i niebuforowane strumienie i działa na nich. Niebuforowane zapisy we / wy nie gwarantują, że dane dotrą na dysk fizyczny - system plików OS może przechowywać kopię danych w nieskończoność, nigdy nie zapisując ich na dysku, jeśli chce. Wymagane jest tylko zatwierdzenie go na dysku podczas wywołaniaflush()
. (Pamiętaj, żeclose()
zadzwoniflush()
w twoim imieniu).źródło
flush()
zagwarantuje, że zostanie zapisany na dysku? Myślałem, że przekazałem go tylko do bufora dysku.O_SYNC
zapewnić, aby zagwarantować zapisy.