Буферизации файла
В этом разделе рассматриваются различные аспекты управления приложениями буферизации файлов, также известные как ввод-вывод небуферированных файлов. Буферизация файлов обычно выполняется системой в фоновом режиме и считается частью кэширования файлов в операционной системе Windows, если не указано иное. Хотя термины кэширование и буферизация иногда используются взаимозаменяемо, в этом разделе термин буферизации используется специально в контексте взаимодействия с данными, которые не кэшируются (буферизуются) системой, где в противном случае они в значительной степени выходят за пределы прямого управления приложениями пользовательского режима.
При открытии или создании файла с помощью функции CreateFile можно указать флаг FILE_FLAG_NO_BUFFERING , чтобы отключить системное кэширование данных, считываемых из файла или записываемых в файл. Хотя это обеспечивает полный и прямой контроль над буферизацией ввода-вывода данных, в случае файлов и аналогичных устройств необходимо учитывать требования к выравниванию данных.
Примечание
Эти сведения о выравнивании применяются к вводу-выводу на таких устройствах, как файлы, поддерживающие поиск, и концепция указателей положения файлов (или смещения). Для устройств, которые не ищут, таких как именованные каналы или устройства связи, отключение буферизации может не требовать определенного выравнивания. Все ограничения или эффективность, которые могут быть получены путем выравнивания в этом случае, зависят от базовой технологии.
В простом примере приложение открывает файл для доступа на запись с флагом FILE_FLAG_NO_BUFFERING , а затем выполняет вызов функции WriteFile с помощью буфера данных, определенного в приложении. В таких случаях этот локальный буфер фактически является единственным буфером файлов, который существует для этой операции. Из-за макета физического диска, макета хранилища файловой системы и отслеживания положения указателя на файл на уровне системы эта операция записи завершится ошибкой, если локально определенные буферы данных не соответствуют определенным критериям выравнивания, описанным в следующем разделе.
Примечание
При обсуждении кэширования не учитывается аппаратное кэширование на самом физическом диске, которое в любом случае не гарантированно будет находиться под непосредственным контролем системы. Это не влияет на требования, указанные в этом разделе.
Дополнительные сведения о взаимодействии FILE_FLAG_NO_BUFFERING с другими флагами, связанными с кэшем, см. в разделе CreateFile.
Требования к выравниванию и доступу к файлам
Как уже говорилось ранее, приложение должно соответствовать определенным требованиям при работе с файлами, открытыми с помощью FILE_FLAG_NO_BUFFERING. Применяются следующие особенности:
- Размеры доступа к файлам, включая необязательное смещение файла в структуре OVERLAPPED , если они указаны, должны иметь значение для числа байтов, которое является целым числом, кратным размеру сектора тома. Например, если размер сектора составляет 512 байт, приложение может запрашивать операции чтения и записи 512, 1024, 1536 или 2048 байт, но не 335, 981 или 7 171 байт.
- Адреса буфера доступа к файлам для операций чтения и записи должны быть выровнены по физическому сектору, то есть выровнены по адресам в памяти, которые являются целыми числами, кратными размеру физического сектора тома. В зависимости от диска это требование может не применяться.
Разработчикам приложений следует обратить внимание на новые типы устройств хранения, которые появляются на рынке с размером физического сектора мультимедиа 4096 байт. Название отрасли для этих устройств — "Расширенный формат". Так как при непосредственном вводе 4096 байтов в качестве единицы адресации для носителя могут возникнуть проблемы с совместимостью, временное решение совместимости заключается в том, чтобы внедрить устройства, которые эмулируют обычное 512-байтовое устройство хранения данных сектора, но предоставляют доступ к сведениям об истинном размере сектора с помощью стандартных команд ATA и SCSI.
В результате такой эмуляции разработчики должны понимать два размера секторов:
- Логический сектор: единица, используемая для адресации логического блока для носителя. Мы также можем рассматривать его как наименьшую единицу записи, которую может принять хранилище. Это эмуляция.
- Физический сектор. Единица, для которой операции чтения и записи на устройство выполняются в одной операции. Это единица атомарной записи, и то, с чем должны быть согласованы небуферированные операции ввода-вывода, чтобы иметь оптимальные характеристики производительности и надежности.
Большинство последних API Windows, таких как IOCTL_DISK_GET_DRIVE_GEOMETRY и GetDiskFreeSpace, возвращают размер логического сектора, но размер физического сектора можно получить с помощью кода элемента управления IOCTL_STORAGE_QUERY_PROPERTY , а соответствующие сведения содержатся в элементе BytesPerPhysicalSector в структуре STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR . Пример см. в примере кода на STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR. Корпорация Майкрософт настоятельно рекомендует разработчикам согласовать небуферированные ввод-вывод с размером физического сектора, как указано в коде управления IOCTL_STORAGE_QUERY_PROPERTY , чтобы обеспечить подготовку приложений к переходу на этот размер сектора.
Windows Server 2003 и Windows XP: Структура STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR недоступна. Он был представлен в Windows Vista и Windows Server 2008.
Так как адреса буфера для операций чтения и записи должны быть выровнены по секторам, приложение должно иметь прямой контроль над выделением этих буферов. Один из способов выравнивания буферов по секторам — использовать функцию VirtualAlloc для выделения буферов. Рассмотрим следующий пример.
- VirtualAlloc выделяет память, выравниваемую по адресам, которые являются целыми числами, кратными размеру страницы системы. Размер страницы составляет 4096 байт в x64 и x86 или 8192 байта для систем на базе Itanium. Дополнительные сведения см. в разделе Функция GetSystemInfo .
- Размер сектора обычно составляет от 512 до 4096 байт для устройств хранения данных с прямым доступом (жестких дисков) и 2048 байт для CD-ПЗУ.
- Размер страницы и сектора — 2.
Таким образом, в большинстве случаев память, выровненная по страницам, также будет выровнена по секторам, так как редки случаи, когда размер сектора больше размера страницы.
Другим способом получения буферов памяти, выровненных вручную, является использование функции _aligned_malloc из библиотеки Run-Time C. Пример управления выравниванием буфера вручную см. в примере кода языка C++ в разделе Пример кода в файле WriteFile.