ищу решение для совместной памяти на основе Windows RAM в C ++ - PullRequest
9 голосов
/ 02 июня 2011

Я сталкиваюсь с ситуацией, когда мне нужно передать до нескольких сотен мегабайт памяти от одного процесса другому.Прямо сейчас я делаю это через файлы, и это слишком медленно.Я предполагаю, что для ускорения эти файлы должны быть записаны непосредственно в ОЗУ и доступны из другого процесса.Не требуется необычная синхронизация.Один процесс будет создавать объекты общей памяти и заполнять их данными.Другой процесс будет читать и удалять их.Однако я провел быстрое исследование, и кажется, что вы не можете совместно использовать память в ОЗУ в Windows - общая память поддерживается файлом или файлом подкачки.Документы boost :: interprocess подтверждают это.Где же скорость, если реализация с разделяемой памятью все еще использует диск?Есть ли какая-либо библиотека C ++, которая использует разделяемую память на основе ОЗУ?

РЕДАКТИРОВАТЬ: я сделал некоторые дополнительные чтения: 1. из boost :: interprocess docs: "поскольку операционная система должна синхронизировать содержимое файла с памятьюсодержимое, отображаемые в память файлы не так быстро, как разделяемая память. "2. из http://msdn.microsoft.com/en-us/library/ms810613.aspx:" Отображенный в память файл также может отображаться более чем одним приложением одновременно. Это представляет собой единственный механизм для двух или болеепроцессы для прямого обмена данными в Windows NT. "

Ответы [ 4 ]

14 голосов
/ 02 июня 2011

Я думаю, что здесь есть фундаментальное недоразумение: вы думаете, что, если вы создадите отображение файла, подкрепленное файлом подкачки, оно будет таким же медленным, как и фактическая запись материала на диск.

Это определенно не тот случай: значение «подкреплено файлом подкачки» в документации означает, что общая память обычно находится в памяти, но у нее есть зарезервированное место в файле подкачки для записи таких данных, если есть недостаточно физической памяти, и диспетчер виртуальной памяти должен выгрузить страницы памяти.

Это не совсем понятно из документации, но страница File Mapping на MSDN подтверждает:

[...] Он поддерживается файлом на диске. Это означает, что когда система заменяет страницы объекта сопоставления файлов , любые изменения, внесенные в объект сопоставления файлов, записываются в файл. Когда страницы объекта сопоставления файлов возвращаются обратно, они восстанавливаются из файла.

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

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

6 голосов
/ 02 июня 2011

Нет ничего плохого в том, что поддерживается файлом - под давлением памяти данные куда-то должны идти, и вы можете выбрать:

  • обрабатывать память как священные данные, которые нельзя выгружать или выгружать

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

  • сбросить память

    Очевидно, не подходит для всех данных. Кэшированное содержимое? Может быть. Оригинальные фото? Вероятно, нет.

  • страница памяти на диск

    Хороший общий выбор!

Видите ли вы давление памяти при использовании инструмента с общей памятью? Добавьте больше оперативной памяти или выясните, как уменьшить ваши системы. :)

3 голосов
/ 02 июня 2011

Насколько я знаю, у вас есть по существу 2 варианта здесь.

1) Вы создаете DLL, используете прагму data_seg и загружаете DLL в оба ваших процесса. Это имеет ОГРОМНЫЕ недостатки, которые подробно объясняются здесь: http://msdn.microsoft.com/en-us/library/h90dkhs0(v=vs.80).aspx

Наиболее важными недостатками являются: пространство должно быть статически инициализировано и храниться в сегменте данных скомпилированной DLL, что означает, что если вы хотите совместно использовать сотни МБ, используя этот метод, то ваша DLL будет сотнями МБ большие.

2) Нет ничего плохого в том, чтобы использовать обычные файлы с отображением в памяти, так как они все равно кэшируются. Вы даже можете использовать системный файл подкачки для хранения данных, как описано в этой статье: http://msdn.microsoft.com/en-us/library/ms810613.aspx

Я на самом деле проверил этот пример [1] межпроцессного взаимодействия С файлом, отображаемым в 1 ГБ, и может подтвердить, что на диск ничего не было записано даже после заполнения всего GiB данными.

[1] http://msdn.microsoft.com/en-us/library/aa366551(v=vs.85).aspx

1 голос
/ 02 июня 2011

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

Если вы действительно хотите читать из памяти другого процесса , используйте Win32 API ReadProcessMemory ().

Если вы не можете хранить данные в оперативной памяти, в MS Windows есть эквиваленты Unix mlock () VirtualLock ()

...