Вам нужен небуферизованный вывод, когда вы хотите убедиться, что вывод был записан, прежде чем продолжить. Одним из примеров является стандартная ошибка библиотеки времени выполнения C - обычно она не буферизуется по умолчанию. Поскольку ошибки (будем надеяться) нечасты, вы захотите узнать о них немедленно. С другой стороны, стандартный вывод в буферном просто потому , что предполагается , что будет гораздо больше данных , проходящих через него.
Другой пример - библиотека журналов. Если ваши сообщения журнала хранятся в буферах вашего процесса, и ваш процесс выгружает ядро, есть очень хороший шанс, что вывод никогда не будет записан.
Кроме того, сводятся к минимуму не только системные вызовы, но и дисковый ввод-вывод. Скажем, программа читает файл по одному байту за раз. При небуферизованном вводе вы будете выходить на (относительно очень медленный) диск для каждого байта, даже если он, вероятно, в любом случае должен читать весь блок (само дисковое оборудование может иметь буферы, но вы все равно выходите на контроллер диска что будет медленнее, чем доступ в память).
При буферизации весь блок считывается в буфер сразу, а затем отдельные байты доставляются вам из (в памяти, невероятно быстро) буферной области.
Имейте в виду, что буферизация может принимать разные формы, например, в следующем примере:
+-------------------+-------------------+
| 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
внутренний буфер объекта (потока) полностью отличается отfgets
необходимого параметра буфера. Это просто сбило меня с толку на несколько часов, прежде чем я написал код, чтобы понять это. QAQВам нужен небуферизованный вывод, когда у вас уже есть большая последовательность байтов, готовая к записи на диск, и вы хотите избежать лишней копии во второй буфер посередине.
Буферизованные выходные потоки будут накапливать результаты записи в промежуточный буфер, отправляя их в файловую систему ОС только тогда, когда накоплено достаточно данных (или они
flush()
запрошены). Это уменьшает количество вызовов файловой системы. Поскольку вызовы файловой системы могут быть дорогими на большинстве платформ (по сравнению с короткимиmemcpy
), буферизованный вывод является чистым выигрышем при выполнении большого количества небольших операций записи. Небуферизованный вывод обычно лучше, если у вас уже есть большие буферы для отправки - копирование в промежуточный буфер не приведет к дальнейшему сокращению количества вызовов ОС и требует дополнительной работы.Небуферизованный вывод не имеет ничего общего с обеспечением того, чтобы ваши данные достигли диска; эта функциональность предоставляется
flush()
и работает как с буферизованными, так и с небуферизованными потоками. Небуферизованная запись ввода-вывода не гарантирует, что данные достигли физического диска - файловая система ОС может хранить копию ваших данных на неопределенный срок, никогда не записывая ее на диск, если захочет. Требуется только зафиксировать его на диске при вызовеflush()
. (Обратите внимание, чтоclose()
позвонитflush()
от вашего имени).источник
flush()
Гарантирует ли звонок, что он будет записан на диск? Я думал, что только передал его в буфер диска.O_SYNC
гарантировать, что пишет.