Если политика для диска в Windows XP и Vista настроена на включение кэширования записи на жесткий диск, есть ли способ очистить только что записанный файл и убедиться, что он был сохранен на диске?
Я хочу сделать это программно на C++.
При закрытии файла происходит сброс на уровне приложения, но не на уровне операционной системы. Если питание отключается от ПК после закрытия файла, но до того, как операционная система очистит кэш записи на диск, файл будет утерян, даже если он был закрыт.
Мы предполагаем, что ваш вопрос касается программирования, но вы не указали среду разработки.





Вы не указали среду разработки, поэтому:
Потоки ввода-вывода имеют метод .Flush, который делает то, что вы хотите.
Существует вызов FlushFileBuffers, который принимает в качестве аргумента дескриптор файла.
ИЗМЕНИТЬ (на основе комментария OA): FlushFileBuffers не требует административных привилегий; это происходит, только если переданный ему дескриптор является дескриптором тома, а не отдельного файла.
Похоже, это сработает. К сожалению, приложение должно работать без прав администратора.
Я не смог найти этот .NET-метод. Насколько я понимаю, единственное место, где фреймворк использует FlushFileBuffers, - это SerialStream. Я подозреваю, что p / вызов FlushFileBuffers - безопасная ставка.
Я обнаружил, что вызов FlushFileBuffers через pInvoke может вызвать исключение (stackoverflow.com/q/9195807/4540). В .NET 4 проще и безопаснее просто вызвать FileStream.Flush (true), как предлагает @jimvfr (stackoverflow.com/a/3992428/4540).
Из документов Microsoft вы должны использовать _flushall и ссылку в COMMODE.OBJ, чтобы гарантировать, что все буферы были зафиксированы на диске.
Нам также пришлось добавить опцию режима "c" во время fopen ()
Вы также должны отметить, что ваши данные могут не сбрасываться на диск действительный, даже при вызове метода очистки вашего API фреймворка.
Вызов метода flush сообщит ядру только о том, что нужно сбросить свои страницы на диск. Однако, если у вас включен дисковый кэш записи, разрешено отложить фактический процесс записи на неопределенное время.
Чтобы гарантировать, что ваши данные будут записаны на физический уровень, вы должны отключить кеш записи в вашей операционной системе. Чаще всего это приводит к снижению производительности на один или два порядка при работе с большим количеством небольших io-операций. Поддержка батарей (ИБП) или диски, которые принимают команды для очистки дискового кэша записи, - еще один вариант решения этой проблемы.
Windows будет принудительно очищать дисковый кеш для важных данных, если для политики диска не установлено значение «Отключить сброс буфера кэша записи Windows».
Конечно будет. Однако, если кэш записи жесткого диска включен, диск может остановить операцию записи. Прочтите, например: support.microsoft.com/kb/259716/EN-US Цитата: «При включении кэширования записи может произойти повреждение файловой системы и / или потеря данных, если в машине произойдет сбой питания, устройства или системы, и она не может быть выключена должным образом».
Фактически, Windows принудительно сбросит кэширование для FlushFileBuffers () независимо от того, была ли включена буферизация кэша записи и даже если была включена очистка кеша записи (ранее известная как «флажок повышенной производительности»).
Вы не должны исправлять это при закрытии файла. Windows будет кэшировать, если вы не откроете файл, передав FILE_FLAG_WRITE_THROUGH в CreateFile ().
Вы также можете пройти FILE_FLAG_NO_BUFFERING; это говорит Windows не хранить копию байтов в кеше.
Согласно документации CreateFile на MSDN, это более эффективно, чем FlushFileBuffers ().
См. Также буферизация файлов и кеширование файлов в MSDN.
.NET FileStream.Flush () НЕ будет очищать кеш Windows для содержимого этого файла; Flush () очищает только внутренний файловый буфер .NET. В .NET 4.0 Microsoft исправила проблему, добавив в Flush () необязательный параметр, который, если задано значение true, вызывает вызов FlushFileSystemBuffers. В .NET 3.5 и ниже ваш единственный выбор - вызвать FlushFileBuffers через pinvoke. См. Комментарий сообщества MSDN FileStream.Flush, чтобы узнать, как это сделать.
ВНИМАНИЕ: .Net 4.0 Flush (true) не исправляет !!!! Отчет об ошибке MS здесь говорит, что file.Flush (true) неисправен, затем исправлен, но не сообщает, в какой версии или пакете обновления он был исправлен! Похоже, ошибка заключалась в том, что если внутренний буфер .NET FileStream пуст, Flush (true) ничего не сделал ??
Смотрите здесь: https://jeffpar.github.io/kbarchive/kb/066/Q66052/
Когда вы изначально открываете файл с помощью fopen, включите опцию режима «c» в качестве ПОСЛЕДНЕЙ ОПЦИИ:
fopen( path, "wc") // w - write mode, c - allow immediate commit to disk
Затем, когда вы хотите принудительно сбросить на диск, вызовите
_flushall()
Мы сделали этот звонок перед звонком
fclose()
У нас возникла именно та проблема, которую вы описали, и этот подход исправил ее.
Обратите внимание, что этот подход НЕ требует административных прав, которые требуются FlushFileBuffersделает, как уже упоминалось другими.
С этого сайта выше:
"Microsoft C / C++ версии 7.0 представляет параметр режима" c "для функции fopen () функция. Когда приложение открывает файл и указывает режим "c", библиотека времени выполнения записывает содержимое файлового буфера на диск, когда приложение вызывает функцию fflush () или _flushall (). "
Вы имеете в виду программно? Вопрос не проясняет