Почему файл с отображением памяти когда-либо должен быть сброшен, когда доступ RDWR?

Я читал одну из реализаций файлов с отображением памяти в golang, https://github.com/edsrzf/mmap-go/. Сначала он описывает несколько режимов доступа:

// RDONLY maps the memory read-only.
// Attempts to write to the MMap object will result in undefined behavior.
RDONLY = 0
// RDWR maps the memory as read-write. Writes to the MMap object will update the
// underlying file.
RDWR = 1 << iota
// COPY maps the memory as copy-on-write. Writes to the MMap object will affect
// memory, but the underlying file will remain unchanged.
COPY

Но в тестовом файле gommap я вижу это:

func TestReadWrite(t *testing.T) {
  mmap, err := Map(f, RDWR, 0)
  ... omitted for brevity...
  mmap[9] = 'X'
  mmap.Flush()

Так зачем ему вызывать Flush, чтобы убедиться, что содержимое записано в файл, если режим доступа RDWR?

Или ОС управляет этим, поэтому пишет только тогда, когда считает нужным?

Если последний вариант, не могли бы вы объяснить его немного подробнее - я читал, что когда ОС не хватает памяти, она записывает в файл и освобождает память. Правильно ли это и относится ли это только к RDWR или только к COPY?

Спасибо


person scc    schedule 18.11.2013    source источник


Ответы (1)


Программа отображает область памяти, используя mmap. Затем он изменяет отображаемую область. Системе не требуется немедленно записывать эти изменения обратно в базовый файл, поэтому вызов read для этого файла (в ioutil.ReadAll) может вернуть предыдущее содержимое файла.

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

Если вам нужно гарантировать, что изменения были записаны в файл в какой-то момент времени, вы должны вызвать msync.

Функция mmap.Flush вызывает msync с флагом MS_SYNC. Когда этот системный вызов возвращается, система записывает изменения в базовый файл, так что любой последующий вызов read будет считывать измененный файл.

Параметр COPY устанавливает сопоставление на MAP_PRIVATE, поэтому ваши изменения никогда не будут записаны обратно в файл, даже если вы используете msync (через функцию Flush).

Прочитайте документацию по POSIX о mmap и msync для получения полной информации.

person rob mayoff    schedule 18.11.2013
comment
Спасибо, поэтому флаг RDWR не означает, что он будет записан немедленно. Записывает ли система в файл только при вызовах mysync или munmap? RDWR — запись в объект MMap приведет к обновлению базового файла. кажется, подразумевается, что когда-нибудь в будущем эти изменения будут записаны, даже если пользователь не вызовет msync или munmap.. В принципе, не могли бы вы прокомментировать последние 2 абзаца вопроса? Спасибо! - person scc; 18.11.2013
comment
@sofia: записи, как правило, ленивы, хотя большую часть времени они практически немедленны из-за унифицированных систем виртуальной памяти (хотя это не то, что гарантировано). Даже когда данные не записываются на диск, последующая операция чтения обычно все равно будет извлекать правильные данные из буферного кеша — однако, вы не знаете, нет никаких гарантий. Программа, которая нуждается в этой гарантии и должна быть переносимой (т. е. не полагаться на реализацию системы), должна сбрасываться, чтобы быть уверенной. - person Damon; 19.11.2013
comment
если я пишу 100 байт за раз до 1 КБ в цикле, может ли он сбрасываться на полпути? или есть ли какая-либо гарантия, что он будет ждать завершения всего 1 КБ и, в конечном итоге, в какой-то момент позже запишется на диск? - person user1870400; 10.10.2020
comment
Система может сбросить ваши записи на полпути. - person rob mayoff; 10.10.2020