2010-05-10 2 views
9

В C++ существует std::fwrite(), который записывает буфер в файл на диске.Имеет ли fwrite буфер выход?

Не могли бы вы рассказать мне, существует ли какой-либо буфер внутри реализации fwrite?

i.e, если я вызываю fwrite() несколько раз (скажем, 10 раз), действительно ли он вызывает файлы ввода/вывода 10 раз?

Я прошу об этом для среды Ubuntu 10.04.

ответ

10

Да, это буферизировано. Размер буфера определяется BUFSIZ. (Спасибо @ladenedge.) Десять достаточно больших операций приведут к десяти системным вызовам.

Вы также можете установить свой собственный буфер, используя std::setbuf и std::setvbuf.

Функции в cstdio наследуются от C. Предпочтительный интерфейс в C++ - fstream и filebuf.

+2

Я считаю, что размер буфера по умолчанию - 'BUFSIZ', как определено в stdio.h, хотя, конечно, абонентам не нужна эта информация. 'setbuf' может использоваться для управления размером в некоторых системах. – ladenedge

+0

Lol, вы отправили это буквально в то же время, что я сделал редактирование: «ladenedge 1 секунда назад» – Potatoswatter

6

Это зависит. На большинстве платформ файл IO кэшируется, поэтому существует вызов fflush() для записи кэшированных данных на диск. В этом отношении ответ на ваш первый вопрос (обычно) «да» и ваш второй «нет». Тем не менее, это не гарантируется тем, что любой фрагмент воображения для какой-либо конкретной платформы - как правило, стандарты определяют только интерфейс для таких функций, а не их реализацию. Кроме того, вполне возможно, что вызов fwrite() вызовет неявный флеш, если кеш станет «полным», и в этом случае вызов fwrite() может фактически инициировать файл IO - особенно при вызове fwrite() с большими объемами данных.

+1

Функции библиотеки IO буферизуются, но также обычно работают функции IO системы; не только это, у контроллера диска тоже есть кеш. На самом деле, обычно проблема с дисками не гарантирует, что ваш выход будет кэшироваться, но убедитесь, что он * действительно * записан на диск, когда вам это нужно.:) –

+0

@Matteo, я знаю, что вы имеете в виду - например, использование fwrite для записи журнала ошибок может быть интересно, если ваша программа сработает * до того, как * кеши будут записаны на диск. К счастью, для этого есть fflush ... – Mac

+0

«Стандарты только определяют интерфейс для таких функций, а не их реализацию» неточно. Хотя стандарт не указывает реализацию, он определяет поведение. И в этом случае стандарт указывает, что FILE * буферизуется (C++ включает стандарт C в 17.3.1.4/1, а стандарт C определяет, что FILE * буферизуется в 7.19.5.6/2). –

0

Это зависит от реализации библиотеки. Вы можете взглянуть на что-то вроде dtruss или strace, чтобы узнать, какие системные вызовы фактически вызывается реализацией.

Зачем вам это нужно?

+0

Моя программа делает много fwrite(). И он работает на Ubuntu 10.04. Я хотел бы знать, нужно ли мне буферизировать IO самостоятельно, прежде чем вызвать функцию fwrite() для повышения производительности. – michael

+0

@michael: Да, буферизуйте ввод-вывод. Уменьшение количества вызовов на 'fwrite' будет как минимум уменьшать количество ветвей вашего кода. Филиалы имеют тенденцию замедлять производительность, так как многие процессоры перезагружают свой кеш команд после ветки. Кроме того, меньшее количество выполняемых программ делает программу более быстрой. –

+0

Почему бы просто не прокомментировать свой код, чтобы найти узкие места? – WhirlWind

0

Я не верю, что стандарты ничего не говорят об этом, но в целом: никакая операционная система не решит, сколько операций ввода-вывода делать. Это может быть 1, это может быть 10. Это может быть даже больше, если размер данных большой. Большинство операционных систем позволяют вам контролировать поведение I/O, но AFAIK нет никакого портативного способа сделать это. (и часто вы все равно не хотите)

2

FILE* I/O может быть буферизирован, но он не обязательно должен быть (он может быть различным для каждого потока). Кроме того, существует множество способов делать буферизацию (полностью буферизуется, когда буфер не сбрасывается до тех пор, пока он не будет заполнен, или явный вызов fflush не будет выполнен или буферизирован в строке, где буфер не будет очищен, пока не увидит EOL). Также можно полностью отключить буферизацию.

Вы можете изменить тип буферизации с помощью вызова setvbuf.

Смежные вопросы