июня 16

Использование проекции файла для реализации разделяемой памяти

Самый низкоуровневый механизм совместного использования данных в одной системе — проецирование файла в память. На нем так или иначе базируются все другие механизмы разделения данных. Поэтому, если вы хотите получить максимальное быстродействие с минимумом издержек, лучше всего применять именно проецирование.
Совместное использование данных в этом случае происходит по следующей схеме. Несколько процессов проецируют в память представления одного и того же объекта «проекция файла», то есть делят одни и те же страницы физической памяти. Поэтому, когда один процесс записывает данные в представление общего объекта «проекция файла», эти изменения немедленно отражаются в других процессах. Но для этого все процессы должны использовать одинаковое имя объекта «проекция файла».
В предыдущем разделе рассматривалось проецирование представления файла, размещенного на диске. Но для целей обмена данными между разными процессами хранение этих данных на диске было бы очень неудобным. К счастью, Win32 API предусматривает возможность проецирования файлов непосредственно на физическую память из страничного файла, а не из специально создаваемого дискового файла.
Этот способ даже проще стандартного, рассмотренного в предыдущем разделе. Во-первых, не нужно вызывать функцию CreateFile. Вы просто вызываете функцию CreateFileMapping и передаете значение INVALID_HANDLE_VALUE (или константу -1) в параметре hFile. Но при вызове функции CreateFileMapping следует передать в последнем ее параметре С-строку, содержащую имя этого объекта. Тогда другие процессы, если им понадобится доступ к разделяемой памяти, смогут вызвать функцию OpenFileMapping и передать ей то же самое имя.
Учтите, что если разделяемая память используется в режиме записи данных более чем одним потоком, то вы должны предусмотреть синхронизацию работы этих потоков. Пример такой синхронизации при помощи объектов-событий рассматривается чуть ниже.
Когда работа с объектом «проекция файла» завершена, процесс должен вызвать функцию CloseHandle. Как только все дескрипторы объекта будут закрыты, система освободит память, переданную из страничного файла.