Использование общей памяти под Windows. Как передать разные данные - PullRequest
2 голосов
/ 30 марта 2009

В настоящее время я пытаюсь реализовать межпроцессное взаимодействие с использованием механизма Windows CreateFileMapping . Я знаю, что мне нужно сначала создать объект сопоставления файлов с помощью CreateFileMapping, а затем создать указатель на фактические данные с помощью MapViewOfFile. Затем в этом примере данные помещаются в файл карты с помощью CopyMemory.

В моем приложении у меня есть буфер изображения (размером 1 МБ), который я хочу отправить другому процессу. Поэтому теперь я запрашиваю указатель на изображение, а затем копирую весь буфер изображения в файл карты. Но мне интересно, действительно ли это необходимо. Разве нельзя просто скопировать фактический указатель в общей памяти, который указывает на данные буфера изображения? Я немного попробовал, но безуспешно.

Ответы [ 6 ]

8 голосов
/ 30 марта 2009

I настоятельно рекомендуем использовать Boost :: interprocess . Он обладает множеством полезных функций для управления подобными вещами и даже включает некоторые специальные функции только для Windows на случай, если вам необходимо взаимодействовать с другими процессами, использующими определенные функции Win32.

Самое важное - использовать смещенные указатели , а не обычные указатели. Смещенные указатели - это, в основном, относительные указатели (они хранят разницу между тем, где находится указатель и где находится указанная вещь). Это означает, что даже если два указателя сопоставлены с разными адресными пространствами, при условии, что сопоставления по структуре идентичны, все в порядке.

Я использовал все виды сложных структур данных со смещенными умными указателями, и это работало как чудо.

8 голосов
/ 30 марта 2009

Разные процессы имеют разные адресные пространства. Если вы передадите действительный указатель в одном процессе другому процессу, он, вероятно, будет указывать на случайные данные во втором процессе. Таким образом, вам придется скопировать все данные.

3 голосов
/ 21 июня 2012

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

В процессе 1:

CreateFileMapping(): он создаст блок общей памяти с именем, указанным в последнем параметре, если он еще не существует, и вернет дескриптор (вы можете назвать его указателем), если он будет успешным.

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

С этим указателем, возвращаемым MapViewOfFile(), только вы можете получить доступ к этому общему блоку.

В процессе 2:

OpenFileMapping(): Если блок общей памяти успешно создан с помощью CreateFileMapping(), вы можете использовать его с тем же именем (имя, используемое для создания блока общей памяти).

UnmapViewOfFile(): он не отобразится (вы можете удалить блок совместно используемой памяти из адресного пространства этого процесса). Когда вы закончите использовать разделяемую память (то есть доступ, изменение и т. Д.), Вызовите эту функцию.

Closehandle(): наконец, чтобы отсоединить блок совместно используемой памяти от процесса, вызовите это с аргументом, дескриптор возвращается OpenFileMapping () или CreateFileMapping ().

Хотя эти функции выглядят простыми, поведение сложно, если флаги не выбраны правильно. Если вы хотите читать или записывать общую память, укажите PAGE_EXECUTE_READWRITE в CreateFileMapping().

Если вы хотите получить доступ к общей памяти после ее успешного создания, используйте FILE_MAP_ALL_ACCESS в MapViewOfFile().

Лучше указать FALSE (не наследовать дескриптор от родительского процесса) в OpenFileMapping(), чтобы избежать путаницы.

2 голосов
/ 29 мая 2009

Вы МОЖЕТЕ получить общую память для использования того же адреса в течение 2 процессов для Windows. Это достижимо несколькими методами.

Использование MapViewOfFileEx , вот важный опыт MSDN.

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

Как правило, предлагаемый адрес используется для указания того, что файл должен быть сопоставлены по одному и тому же адресу в нескольких процессы. Это требует области адресное пространство будет доступно во всех вовлеченные процессы. Нет другой памяти распределение может иметь место в регион, который используется для картирования, в том числе использование VirtualAlloc или функцию VirtualAllocEx для резервирования память.

Если параметр lpBaseAddress указывает базовое смещение, функция успешно, если указанная память регион еще не используется вызывающий процесс. Система не убедитесь, что та же область памяти доступно для файла сопоставленной памяти в других 32-битных процессах.

Еще одна связанная техника - использовать DLL с разделом, помеченным как Read + Write + Shared. В этом случае ОС в значительной степени выполнит вызов MapViewOfFileEx для вас и для любого другого процесса, который загружает DLL.

Возможно, вам придется пометить вашу DLL на фиксированный адрес загрузки, нельзя перемещать и т. Д. Естественно.

0 голосов
/ 30 марта 2009

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

0 голосов
/ 30 марта 2009

Вы можете использовать Marshalling указателей.

...