Файлы с отображением памяти могут использоваться либо для замены доступа для чтения / записи, либо для поддержки одновременного совместного использования. Когда вы используете их для одного механизма, вы получаете и другой.
Вместо того, чтобы искать, писать и читать в файле, вы отображаете его в память и просто обращаетесь к битам там, где вы их ожидаете.
Это может быть очень удобно и в зависимости от интерфейса виртуальной памяти может повысить производительность. Повышение производительности может произойти, потому что операционная система теперь может управлять этим бывшим «файловым вводом-выводом» вместе со всем вашим другим программным доступом к памяти и может (теоретически) использовать алгоритмы разбиения на страницы и т. Д., Которые она уже использует для поддержки виртуальная память для остальной части вашей программы. Однако это зависит от качества вашей базовой системы виртуальной памяти. Я слышал анекдоты, в которых говорится, что системы виртуальной памяти Solaris и * BSD могут показать лучшие улучшения производительности, чем система виртуальных машин Linux, но у меня нет эмпирических данных, подтверждающих это. YMMV.
Параллелизм становится очевидным, если учесть возможность того, что несколько процессов используют один и тот же «файл» через отображаемую память. В модели чтения / записи, если два процесса записывают данные в одну и ту же область файла, вы можете быть уверены, что данные одного процесса поступят в файл, перезаписав данные другого процесса. Вы получите одно или другое, но не какое-то странное смешение. Я должен признать, что не уверен, соответствует ли такое поведение каким-либо стандартам, но на это можно в значительной степени положиться. (На самом деле это хороший дополнительный вопрос!)
Напротив, в нанесенном на карту мире представьте себе два процесса, оба «пишущие». Они делают это, создавая «хранилища памяти», что в конечном итоге приводит к тому, что операционная система выгружает данные на диск. Но тем временем можно ожидать перекрывающихся операций записи.
Вот пример. Скажем, у меня есть два процесса, которые записывают 8 байтов со смещением 1024. Процесс 1 записывает «11111111», а процесс 2 записывает «22222222». Если они используют файловый ввод-вывод, то вы можете представить себе, что глубоко внутри O / S есть буфер, полный единиц, и буфер, полный двоек, оба направляются в одно и то же место на диске. Один из них доберется туда первым, а другой - вторым. В этом случае выигрывает второй. Однако , если я использую файловый подход с отображением памяти, процесс 1 перейдет в хранилище памяти размером 4 байта, за которым следует другое хранилище памяти из 4 байтов (предположим, что это не максимальный размер хранилища памяти). Процесс 2 будет делать то же самое. В зависимости от того, когда выполняются процессы, вы можете ожидать увидеть любое из следующего:
11111111
22222222
11112222
22221111
Решением является использование явного взаимного исключения, что, вероятно, в любом случае является хорошей идеей. В любом случае, вы вроде бы полагались на то, что операционная система сделает «правильные вещи» при чтении / записи файлового ввода-вывода.
Классифицирующим примитивом взаимного исключения является мьютекс. Для файлов с отображением памяти я бы посоветовал вам взглянуть на мьютекс с отображением в память, доступный с помощью, например, pthread_mutex_init ().
Редактируйте с одной хитростью: когда вы используете сопоставленные файлы, существует соблазн встроить указатели на данные в файле, в самом файле (подумайте, что связанный список хранится в сопоставленном файле). Вы не хотите этого делать, поскольку файл может отображаться по разным абсолютным адресам в разное время или в разных процессах. Вместо этого используйте смещения в сопоставленном файле.