Файлы с отображением в памяти в системе POSIX синхронизируются - PullRequest
1 голос
/ 11 ноября 2010

Почему следующий код работает правильно?

void continuous_mmap (void)
{
 struct stat buf;
 int fd = open("file_one", O_RDONLY), i;
 char *contents;

 fstat(fd, &buf);
 contents = mmap(NULL, buf.st_size, PROT_WRITE, MAP_PRIVATE, fd, 0);
 close (fd);
 mprotect(contents, buf.st_size, PROT_READ);
 for (i = 0; i < 15; i++) {
  printf ("%s\n", contents);
  sleep (1);
 }
 munmap(contents, buf.st_size);
}

Во-первых, файл остается синхронизированным (редактирование и сохранение файла автоматически приводит к печати обновленного содержимого), даже при добавлении. Как мой код может получить доступ к указанному количеству байтов (начальный размер файла) без сегфагов? Это потому, что mmap всегда округляет длину до размера системной страницы? Если да, может ли это поведение зависеть от POSIX систем в целом (я не нашел такого требования в справочной странице mmap).

Во-вторых, как к тексту автоматически добавляется '0'? Это потому, что не отображенные байты автоматически обнуляются? Можно ли от этого поведения зависеть?

Ответы [ 3 ]

2 голосов
/ 11 ноября 2010

да, стандарт гласит

Система всегда должна заполнять нулями любые частичная страница в конце объекта. Кроме того, система никогда не должна писать любые измененные части последнего страница объекта, которые находятся за его пределами конец.

  • Если это так, может ли это поведение зависеть в системах POSIX в целом (я не смог найти ни одного такого требования на странице руководства mmap).

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

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

1 голос
/ 11 ноября 2010

POSIX даже не требует нетривиального размера страницы;теоретически реализация может иметь размер страницы в 1 байт.Точно так же чтение нулей с остальной части страницы после размера файла, кажется, не определено.Я мог бы представить себе некоторые неработающие реализации, в которых утечка старого содержимого файлов, которые были усечены здесь, но я бы посчитал это серьезным нарушением безопасности / конфиденциальности, которое сделало бы такую ​​реализацию неуместной в реальном мире.Конечно, они могли бы заполнить пространство 0xDEADBEEF, и тогда вам не повезло.

Даже если бы вы могли предполагать заполнение нулями (что, вероятно, имеет место в большинстве реальных операционных систем),Я бы предостерег от того, чтобы когда-либо использовать это.Что произойдет, если ваш файл будет кратным системному размеру страницы?Внезапно ваш код перестает читать после конца, или (возможно, хуже) читает с несвязанной страницы, которая, как оказалось, была сопоставлена ​​рядом с отображением вашего файла.Это очень и очень неприятная ошибка, которую вы, вероятно, не поймете, потому что вероятность наличия текстового файла, кратного системному размеру страницы, весьма мала.

0 голосов
/ 11 ноября 2010

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

Если ваше приложение изменило contents[0] перед циклом, оно не увидит внешние изменения.

...