Файловая система: перезапись данных одинаковой длины

У меня есть проект, в котором мне приходится очень часто обновлять данные на диске в случае отключения питания. При перезаписи ровно 512b (1 сектор моего диска) в файле с данными одинаковой длины файловая система отмечает измененные сектора и обновляет их на диске, когда они готовы к очистке? Или он записывает весь файл каждый раз, когда сбрасывает изменение? Меня в основном интересует ext4, но мне любопытно, одинаково ли это с каждой файловой системой.

Если стандартом является не отслеживание изменений, а перезапись всего файла, есть ли способ изменить это? Какие-то варианты записи?


person Shenanigans    schedule 01.08.2016    source источник


Ответы (1)


Как правило, в Linux файлы кэшируются в кэше страниц, и на уровне страницы отслеживается, является ли страница грязной. На платформах Intel x86 размер страницы составляет 4 КБ, поэтому, если вы испортите страницу 4 КБ, это страница 4 КБ будет записана обратно.

Если вы хотите перезаписать только один 512-байтовый сектор, и у вас есть жесткий диск с 512-байтовыми секторами, вы можете открыть файл с флагом O_DIRECT, и если вы выполните запись 512 байт, по смещению файла, которое кратно 512 байт, а буфер памяти, из которого вы производите запись, также выровнен по 512 байтам, тогда вы можете обойти кеш страниц, и запись пойдет прямо на диск (отсюда O_DIRECT).

Обратите внимание, что некоторые современные диски действительно используют физический сектор размером 4 КБ, но они эмулируют секторы размером 512 байт по соображениям обратной совместимости. Эти диски иногда называют секторами 512e (e для эмуляции). На этих дисках, если вы выполняете запись сектора размером 512 байт, диск будет выполнять цикл чтения-изменения-записи, поскольку внутри диска за один раз можно записывать только 4 КБ. Это будет заметно вам как удар по производительности, но с функциональной точки зрения он будет выглядеть так же, как традиционный старомодный жесткий диск с 512 секторами.

person Theodore Ts'o    schedule 01.08.2016
comment
И в файле размером 1 МБ, если бы я написал 300 байт из сектора 512 байт, он все равно перезаписал бы только один сектор? Он просто выполнит чтение для других 212b, прежде чем стереть сектор для перезаписи? - person Shenanigans; 02.08.2016
comment
Если вы используете прямой ввод-вывод, вы должны выполнить прямое чтение ввода-вывода, за которым следует прямая запись ввода-вывода, а операции прямого ввода-вывода должны следовать правилам прямого ввода-вывода, поэтому вам придется выполните чтение с выравниванием по 512, измените 300 байт, а затем выполните прямую запись ввода-вывода, также следуя правилам прямого ввода-вывода --- поэтому буфер должен быть выровнен по границе 512 байт, и смещение, которое вы запись должна быть выровнена по 512 байтам, а длина должна быть кратна 512 байтам. - person Theodore Ts'o; 04.08.2016
comment
Если вы выполняете буферизованную запись, то она будет проходить через кэш страниц, а это означает цикл чтения/изменения/записи 4 КБ. - person Theodore Ts'o; 04.08.2016