Страницы

Поиск по вопросам

суббота, 13 октября 2018 г.

Повреждение файлов при отключении питания и исключениях в процессах

Я занимаюсь разработкой автономных систем управления и анализа для тяжелой промышленности. Использую язык C (C99-C11). Очень беспокоит вопрос повреждения файлов и файловых систем, использующихся в Windows (Embedded, CE и пр.) при внезапном обесточивании или при жестком прерывании рабочего процесса/потока, например из-за исключения.
Хотелось бы разобраться в этом вопросе, достойной литературы по этой теме найти не удалось. Посоветуйте что-нибудь, желательно не на английском языке. Или, может быть, кто-нибудь сможет упрощенно объяснить следующее:
Ясное дело, если мы открыли файл и пишем в него, и в этот момент происходит отключение питание, или возникает фатальное исключение в одном из потоков процесса, то операция прерывается на полпути. Это практически гарантированно приводит к повреждению файла/файловой системы в том районе, где происходит работа.
Но ведь даже если мы не работаем с файлом, а в этот момент отключается питание, файл может быть поврежден из-за того, что ОС в фоновом режиме занимается дефрагментацией/индексацией. Это так? Есть ли гарантия, что после возврата управления в программу после функций fclose() или fwrite() данные гарантированно корректно занесены на носитель?
Например, ситуация:
Процесс имеет два потока, в одном потоке происходит сохранение данных в файл, а в другом возникает ситуация, после которой мы можем лишь завершить процесс. Например, посреди сложной логики malloc() вернул NULL, или отказало устройство, или еще что.
Я предполагал защитить файл критической секцией, и использовать эту же критическую секцию для инициации аварийного завершения. Тогда, предположительно, после того как работа с файлом закончится, критическая секция освободится, и второй поток сможет в нее зайти и вызвать abort() или аналогичную функцию планируемого жесткого прерывания процесса.
Проблема на мой взгляд в том, что даже после того, как мы сделали fopen() + fwrite() + fclose(), нет гарантий, что файл корректно сохранен, а не гуляет где-то в буферах, которые связаны с нашим процессом. И как контролируется процесс переноса данных из внутреннего промежуточного буфера-кэша жесткого диска на сам носитель?
Например, файл записан и закрыт, и даже процесс, который все это делал, уже закрыт. Но данные частично или полностью еще находятся во внутреннем буфере-кэше накопителя. Если в этот момент произойдет обрыв питания, то данные, я почти уверен, будут повреждены или уничтожены.
Как ОС отслеживает перед своим завершением факт того, что данные из буфера накопителя записаны окончательно?


Ответ

Но ведь даже если мы не работаем с файлом, а в этот момент отключается питание, файл может быть поврежден из-за того, что ОС в фоновом режиме занимается дефрагментацией/индексацией. Это так?
Во-первых, сомневаюсь, что драйвер самостоятельно будет дефрагментировать что-либо (хотя и не буду утверждать обратное), а отсутствие насущности проблемы фрагментации объясняется в первую очередь грамотными алгоритмами выбора блоков для хранения файлов.
А критические, неустранимые ошибки ФС в таких случаях — это практически невероятный сценарий (скажем, внезапный отказ HDD — куда более вероятен). Но повреждения данных (файлов) с которыми велась активная работа в момент отказа — штатная ситуация.
2) Есть ли гарантия, что после возврата управления в программу после функций fclose() или fwrite() данные гарантированно корректно занесены на носитель?
Нет.
fwrite () гарантирует только занесение данных в пользовательский буфер, но не гарантирует, что эти данные будут переданы ОС. Чтобы принудительно сбросить пользовательский буфер есть функция fflush (). При скоропостижной кончине процесса данные могут быть потеряны. fclose () и fflush () сбрасывают пользовательский буфер, но не гарантируют, что ОС передаст данные на носитель. Если процесс умрёт после их возврата, то изменения не потеряются, но они могут быть потеряны в случае внезапного отключения питания.
3) И как контролируется процесс переноса данных из внутреннего промежуточного буфера-кэша жесткого диска на сам носитель?
Для того чтобы гарантировать запись данных на диск средств Си недостаточно, необходимо пользоваться API ОС. В POSIX-системах (и в linux в частности) есть вызов fsync (). Он гарантирует, что вернёт управление (само собой без ошибки) только после того как данные физически попадут на диск и переживут внезапный отказ системы. В Win API аналогом FlushFileBuffers (), согласно документации он сбрасывает системные буферы, но, гарантирует ли сброс буферов самого HDD или нет, я не знаю.
Как ОС отслеживает перед своим завершением факт того, что данные из буфера накопителя записаны окончательно?
Просто посылает определённую команду HDD. Например, в ATA она так и называется, FLUSH CACHE, опкод E7h. (здесь должен быть ещё десяток оговорок, которые должны быть интересны только разработчикам драйверов)

Комментариев нет:

Отправить комментарий