Выполняется ли запись в файл без поиска по sh байт последовательно во всех файловых системах? - PullRequest
1 голос
/ 18 июня 2020

Пишу JSON файлов. Это означает, что для каждого символа '{' существует соответствующий '}', а последний байт в файле - '}'. Запись происходит последовательно. Нет фсэков. Таким образом, если запись в файл каким-то образом прервана, я ожидаю получить неверный JSON файл.

Теперь гипотетическая файловая система может решить передать sh мои байты не по порядку. Это означало бы, что если отключение электроэнергии произойдет во время записи, до того, как все будет сброшено, я могу получить действительный JSON, который не содержит данных, которые я намеревался. Я мог бы использовать строку "xxx" вместо "yyy" или отсутствующие цифры в конце чисел.

Существует ли такая файловая система? Могу ли я полагаться на тот факт, что если файл действителен, то он гарантированно будет полным?

Изменить: этот вопрос относится к случаю, когда данные не могут быть действительными, если отсутствует последний байт. JSON является здесь иллюстративным. Технически 42342 - это действительный JSON, который не может быть подтвержден, если он неполный.

1 Ответ

1 голос
/ 21 июня 2020

Существует несколько причин, по которым файловая система может sh вывести ваши страницы из строя:

  • Страница содержит данные из 2 файлов, а другой файл сбрасывается на диск.
  • Страница находится за пределами рабочего набора процесса (и поэтому не стоит кэшировать), а ОС требуется память для других целей.
  • Файловая система распространяется, например, OrangeFS или Andrew Filesystem, и воспроизводится очень разные правила реализации.
  • Файловая система NFS, выходящая на более сложный распределенный, разнородный набор устройств, где некоторые записи полностью синхронны, а приложение ни в чем не умнее.

И это не так. только файловая система, но также и нижележащее устройство. концепции файлов).

Блочное устройство может быть чередующимся (RAID 0), так что одно устройство может сбрасывать u sh перед другим.

Тем не менее, очень маловероятно, что произойдет потеря 3 байтов, например, xxx, после cra sh. Более вероятно, что произойдет потеря блоков, например, кратных 4096 байт.

По правде говоря, большинство файловых систем практически не дает никаких гарантий относительно целостности данных, записанных во время sh (в отличие от метаданных).

Когда требуется атомарность, приложения обычно используют rename(2) или его эквиваленты:

  1. Запись во временный файл, например, с помощью POSIX write(2).
  2. Flu sh файл, например, с POSIX fsync(2) и закройте его.
  3. Переименуйте файл в целевое имя, например с POSIX rename(2).

Все известные мне файловые системы POSIX, которые находятся в активном использовании, реализуют переименование POSIX в cra sh -безопасном режиме, я предполагаю, что NTFS работает как хорошо.

Но, очевидно, POSIX не требует этого строго. Поскольку вы пишете новые файлы, это не проблема, но если вы хотите быть лишним параноиком, вы можете добавить еще один шаг:

Удалить временный файл (игнорировать ошибку, если он не существует).
...