Я экспериментирую с файлом с отображением памяти в Linux, и у меня возник вопрос о том, что на самом деле происходит при отображении одного и того же файла из разных процессов и записи после конца файла.
Я вручную создал файл с vim и записал туда 2 байта:
$ cat test_mmap
aa
Тогда я написал 2 очень простые программы.
Первая программа отображает файл и изменяет сопоставление без msync
и munmap
.
writer.c
:
int main(void){
int fd = open("/tmp/test_mmap", O_CREAT | O_RDWR, S_IRWXU);
char *mapped_region = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_WRITE, MAP_SHARED, fd, 0);
mapped_region[0] = '0';
mapped_region[1] = '1';
mapped_region[2] = '2';
mapped_region[3] = '3';
mapped_region[4] = '4';
mapped_region[5] = '5';
}
Второй читает карту.
reader.c
int main(void){
int fd = open("/tmp/test_mmap", O_CREAT | O_RDWR, S_IRWXU);
char *mapped_region = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_WRITE, MAP_SHARED, fd, 0);
printf("%c\n", mapped_region[0]);
printf("%c\n", mapped_region[1]);
printf("%c\n", mapped_region[2]);
printf("%c\n", mapped_region[3]);
printf("%c\n", mapped_region[4]);
printf("%c\n", mapped_region[5]);
}
Итак, я побежал
$ ./writer && ./reader && cat /tmp/test/test_mmap
0
1
2
3
4
5
012
Это означает, что любые данные, записанные за пределами файла, сохраняются в отображении в течение некоторого времени (хотя они не записываются в файл), и если другой процесс, следовательно, отображает ту же область, данные, записанные за пределами, не обнуляются как указано в man-странице :
Файл отображается кратно размеру страницы. Для файла, который не
кратный размеру страницы, оставшаяся память обнуляется, когда
сопоставлены и записи в этот регион не записываются в файл.
Запуск считывателя с perf -e major-faults ./reader
показывает, что
0 major-faults
означает, что никакие страницы не читаются с диска. Также, глядя на /proc/<pid_writer>/smaps
, я заметил, что страница помечена как грязная и закрытая (даже если отображение было создано с флагом MAP_SHARED
):
7fc80f279000-7fc80f27a000 -w-s 00000000 fd:00 6057290 /tmp/test_mmap
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 4 kB
Если через некоторое время я запустил процесс чтения (какое время требуется для ожидания?), Я заметил, что
$ ./reader
0
1
2
Вопрос: Правильно ли и где-то задокументировано, что если один процесс изменяет отображение за концом файла, страница помечается как грязная и до тех пор, пока страница грязная и другой процесс отображает ту же область того же файла, данные, записанные ранее процессом, не обнуляются и не сохраняются как некоторое время?