Как получить общий объект в общей памяти - PullRequest
1 голос
/ 25 января 2010

Наше приложение зависит от внешней, поставляемой третьей стороной конфигурации (включая настраиваемые функции вождения / принятия решений), загружаемой в виде файла .so.

Независимо от этого, он взаимодействует с внешними модулями CGI, используя кусок общей памяти, где сохраняется почти все его энергозависимое состояние, так что внешние модули могут читать его и модифицировать, где это применимо.

Проблема в том, что для модулей CGI требуется много постоянных данных конфигурации из .so, а главное приложение выполняет совершенно ненужное копирование между двумя областями памяти, чтобы сделать данные доступными. Идея состоит в том, чтобы сделать весь Shared Object для загрузки в Shared Memory и сделать его напрямую доступным для CGI. Проблема в том, как?

  • dlopen и dlsym не предоставляют никаких средств для назначения места загрузки SO-файла.
  • мы пробовали shmat (). Кажется, он работает только до тех пор, пока какой-нибудь внешний CGI не попытается получить доступ к общей памяти. Тогда указанная область выглядит такой же закрытой, как если бы она никогда не использовалась. Может, мы что-то не так делаем?
  • загрузка .so в каждом скрипте, который в этом нуждается, исключена. Огромный размер структуры, связанный с частотой вызовов (некоторые скрипты вызываются один раз в секунду для генерации обновлений в реальном времени), и это встроенное приложение делает его бездействующим.
  • просто memcpy () тоже не подходит для вставки .so в shm - некоторые структуры и все функции связаны через указатели.

Ответы [ 4 ]

3 голосов
/ 25 января 2010

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

При загрузке файла .so загружается только одна копия кода файла .so (отсюда термин общий объект).

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

2 голосов
/ 30 января 2010

Полагаю, самым простым вариантом было бы использовать файл с отображенной памятью, что уже предложил Нил. Если этот параметр не заполняет должным образом, альтернативой может быть определение выделенного распределителя. Вот хорошая статья об этом: Создание контейнеров STL в общей памяти

Существует также отличная библиотека Boost.Interprocess Иона Газтаньяги с shared_memory_object и соответствующими функциями. Ион предложил решение для комитета по стандартизации C ++ для будущего TR: Файлы с отображенной памятью и Общая память для C ++ что может указывать на то, что стоит рассмотреть это решение.

2 голосов
/ 25 января 2010

Поместить фактические объекты C ++ в разделяемую память, как вы уже обнаружили, очень и очень сложно. Я настоятельно рекомендую вам не идти по этому пути - помещать данные, которые должны быть разделены, в общую память или в отображенный файл памяти намного проще и, вероятно, будет гораздо более надежным.

0 голосов
/ 29 января 2010

Вам нужно реализовать сериализацию объекта Функция сериализации преобразует ваш объект в байты, затем вы можете записать байты в SharedMemory и иметь свой модуль CGI для десериализации байтов обратно в объект.

...