Буферизация при чтении функциями С и Win32
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.217.2] |
|
|
Правила раздела Visual C++ / MFC / WTL (далее Раздела)
FAQ Раздела
Обновления для FAQ Раздела
Поиск по Разделу
MSDN Library Online
Буферизация при чтении функциями С и Win32
|
|
|
|
|
Меня заинтересовал вопрос о буферизации ввода-вывода и я решил попробовал проверить, так ли я все понимаю, на конкретной программе. В ней читается один и тот же файл функциями С и Win32 с включенной буферизацией и выключенной. Удобно смотреть, как это работает, на примере чтения небольшого файла (я смотрел на файле 10 мб) с CD. Функция Win32 CreateFile действительно отключает буферизацию (файл читается с диска постоянно, индикатор горит), а функция setvbuf буферизацию не отключает (файл читается один раз, индикатор гаснет, но в программе чтение происходит). Правильно ли я понимаю принципы работы этой программы в Windwows (программу прилагаю):
1. Windows выделяет свои буферы для операций чтения-записи файла в рамках функции CreateFile . Если я отключаю буферизацию, а в программе использую свой буфер, то windows создает в памяти только буфер, который я выделяю в своей программе, никаких других буферов не используется. В связи с этим все время читается файл с диска CD. 2. Если я буферизацию не отключаю, то Windows при работе функции CreateFile выделяет свои буферы (буфер1) (интересно, исходя из каких принципов определяется размер этих буферов) и, кроме того, создает буфер, который я выделяю в своей программе (буфер2). При чтении файл читается в буфер1 и, если он умещается целиком, далее в буфер2 он читается из буфера1. Поэтому индикатор дисковода не горит. 3. Я думал, что при использовании функции С будут достигаться те же результаты, что и при использовании функций Win32 (думал, что при компиляции в exe идут вызовы функций Win32) и думал, что setvbuf отключает буферизацию Windows (bufer1). Однако, как показывает программа, это не так (если я все правильно делаю). Покритикуйте, пожалуйста, мои взгляды на буферизацию и объясните, пожалуйста, почему не работает setvbuf. Прикреплённый файл Bufer.zip (28.79 Кбайт, скачиваний: 106)
|
|
Сообщ.
#2
,
|
|
|
|
Во-первых, я уже говорил, что setvbuf не имеет и не может иметь никакого отношения к буферизации ОС. Сам подумай - FILE_FLAG_NO_BUFFERING можно задать только при открытии файла CreateFile, а setvbuf можно использовать только для уже открытого файла. Поэтому если бы в C была возможность отключать буферизацию ОС, то она должна была бы сидеть в параметрах fopen, но никак не в функциях, работающих с уже открытым файлом.
Во-вторых, не путай функции приложения и ОС. Грубо говоря к ОС относится функции ядра и та часть юзермодного АПИ, на которую ты или не можешь повлиять вообще или только в пределах, представляемых этим АПИ. В частности буферизацию файлов в ОС можно только включить\выключить (FILE_FLAG_NO_BUFFERING) и косвенно\частично повлиять на механизм буферизации (FILE_FLAG_SEQUENTIAL_SCAN), но все тонкости буферизации ОС оставляет за собой. Все остальное относится к самому приложению, в т.ч. и fopen и setvbuf - хочешь используй, хочешь не используй или вообще пиши на чистом АПИ, хочешь используй свой буфер, хочешь не используй. Поэтому не "windows создает буфер, который я использую в программе", а ты сам создаешь этот буфер, используя средства АПИ или С\С++. Ну и функции С это ес-но просто часть кода твоего приложения, написанная за тебя добрыми дядями с целью упрощения\унификации\портируемости и т.д.и т.п. В-третьих, судя по твоему коду, похоже ты не понял предназначение setvbuf. Не понимаю, как тебе пришло в голову выделить буфер, назначить его в setvbuf и затем в него же читать fread ?! Буферирование стрима нужно только при чтении текстовых файлов и малых порций двоичных данных (например, в дельфи\паскале для двоичных файлов внутренняя буферизация вообще не предусмотрена - только для текстовых). В этом сл.увеличение размера буфера положительно сказывается на производительности, т.к. уменьшается число обращений к ReadFile и связанных с эти накладных расходов на переключение юзер-мод\кернел-мод. Если же есть возможность\желание читать двоичные данные большими блоками, то логичнее отключать буферизацию стрима установкой _IONBF и читать данные прямо в свой буфер. |
|
Сообщ.
#3
,
|
|
|
|
Спасибо большое за подробное объяснение, видимо, мне надо поглубже разобраться с понятиями ввода-вывода в С (С++) и ОС. Сейчас у меня какая-то каша в голове, буду приводить голову в порядок.
|