Память Mapped файлов и атомная запись одиночных блоков

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

Как добиться такого же эффекта для файла с отображением памяти?

Файлы с отображением памяти представляют собой просто массивы байтов, поэтому, если я изменяю массив байтов, операционная система не может знать, когда я считаю запись "сделанной", поэтому она (даже если это маловероятно) заменяет память только в середине моей операции записи блоков, и в сущности я пишу половину блока.

Мне понадобится какая-то "критическая секция ввода/выхода" или какой-то метод "закрепления" страницы файла в памяти, пока я пишу вам. Что-то подобное существует? Если да, то переносится ли она через общие системы POSIX и Windows?

Ответ 1

Метод ведения журнала кажется единственным способом. Я не знаю, как это работает с несколькими приложениями, написанными в один и тот же файл. В проекте Cassandra есть хорошая статья о том, как получить производительность в журнале. Главное в том, чтобы убедиться в том, что журнал регистрирует только положительные действия (мой первый подход заключался в том, чтобы написать предварительный образ каждой записи в журнал, позволяющий откат, но он получил чрезмерное сложный).

Таким образом, в основном ваш файл с отображением памяти имеет transactionId в заголовке, если ваш заголовок вписывается в один блок, вы знаете, что он не будет поврежден, хотя многие люди, похоже, дважды записывают его с помощью контрольной суммы: [header[cksum]] [header[cksum]], Если первая контрольная сумма не удалась, используйте вторую.

Журнал выглядит примерно так:

[beginTxn[txnid]] [offset, length, data...] [commitTxn[txnid]]

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