Буферизований проти небуферованого вводу-виводу


83

Я довідався, що за замовчуванням введення-вивід у програмах буферизується, тобто вони подаються з тимчасового сховища до програми, що запитує. Я розумію, що буферизація покращує продуктивність вводу-виводу (можливо, зменшуючи системні дзвінки). Я бачив приклади вимкнення буферизації, як setvbufу C. У чому різниця між двома режимами і коли один слід використовувати над іншим?

Відповіді:


123

Ви хочете небуферований вихід, коли хочете переконатися, що результат був записаний перед продовженням. Одним із прикладів є стандартна помилка в бібліотеці середовища виконання 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
Рік

35

Вам потрібен негарний вихід, коли у вас вже є велика послідовність байтів, готових до запису на диск, і ви хочете уникнути зайвої копії у другий буфер посередині.

Буферовані вихідні потоки накопичуватимуть результати запису в проміжний буфер, надсилаючи їх до файлової системи ОС лише тоді, коли накопичиться (або flush()буде запитано) достатня кількість даних . Це зменшує кількість викликів файлової системи. Оскільки виклики файлової системи можуть бути дорогими на більшості платформ (порівняно з короткими memcpy), буферизоване виведення є чистим виграшем при виконанні великої кількості невеликих записів. Небуферизований вихід, як правило, кращий, коли у вас вже є великі буфери для надсилання - копіювання в проміжний буфер не зменшить кількість викликів ОС далі і створює додаткову роботу.

Небуферизований вихід не має нічого спільного з тим, що ваші дані потрапляють на диск; ця функціональність забезпечується flush()і працює як на буферизованих, так і на небуферованих потоках. Небуферовані записи вводу-виводу не гарантують, що дані потрапили на фізичний диск - файлова система ОС може вільно тримати копію ваших даних необмежено довго, ніколи не записуючи їх на диск, якщо вона цього хоче. Потрібно лише зафіксувати його на диску, коли ви викликаєте flush(). (Зверніть увагу, що close()буде дзвонити flush()від вашого імені).


Чи flush()гарантуватиме виклик, що він записаний на диск? Я думав, що передав його лише в буфер диска.
jrdioko

2
Вам потрібно O_SYNCзабезпечити гарантування записів.
moshbear

Небуферовані IO-файли про запис на диск. Звідси термін не буферизований (без проміжного буфера, але безпосередньо записаний на диск) для winapi, який ви називаєте CreateFile з FILE_FLAG_NO_BUFFERING та FILE_FLAG_WRITE_THROUGH, щоб забезпечити пряме збереження даних після кожного запису. Для деяких інших idont знаю.
Мартін Косіцкі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.