Совместное использование указателя в программах на C ++ - PullRequest
0 голосов
/ 29 августа 2018

Это относится к предыдущему сообщению:

Выделение большого блока памяти в C ++

Я бы хотел, чтобы работал один сервер C ++, генерирующий гигантскую матрицу M. Затем на той же машине я хотел бы запустить другие программы, которые могут связаться с этим сервером, и получить адрес памяти для M. M только для чтения, и сервер создает его один раз. Я должен иметь возможность порождать клиента ./test, и эта программа должна иметь доступ только для чтения к M. Сервер всегда должен быть запущен, но я могу в любое время запустить другие программы, например ./test.

Я не очень разбираюсь в C ++ или ОС, как лучше всего это сделать? Должен ли я использовать потоки POSIX? Матрица является примитивным типом (double, float и т. Д.), И все программы знают ее размеры. Клиентским программам требуется вся матрица, поэтому я не хочу, чтобы задержка от копии мема с сервера на клиент, я просто хочу поделиться этим указателем напрямую. Какие мои лучшие варианты?

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Один из механизмов межпроцессного взаимодействия, который вы определенно можете использовать для совместного использования прямого доступа к вашей матрице M, - это общая память . Это означает, что ОС позволяет нескольким процессам получать доступ к общему сегменту в памяти, как если бы он находился в их адресном пространстве, сопоставляя его для каждого запрашивающего. Решение, которое отвечает всем вашим требованиям, а также является кроссплатформенным, - boost :: interprocess . Это тонкий переносимый уровень, который охватывает все необходимые вызовы ОС. Смотрите рабочий пример справа здесь, в документе .

По сути, вашему серверному процессу просто нужно создать объект типа boost::interprocess::shared_memory_object, предоставив конструктору имя для общего сегмента. При вызове метода truncate() ОС будет искать достаточно большой сегмент в адресном пространстве этого серверного процесса. С этого момента любой другой процесс может создать объект того же типа и предоставить то же имя . Теперь он тоже имеет доступ к точно такой же памяти. Копии не принимаются.

Если по какой-то причине вы не можете использовать переносимые библиотеки Boost или по другой причине хотите ограничить поддерживаемую платформу для Linux, используйте POSIX API вокруг функции mmap() . Вот справочная страница Linux . Использование в основном недалеко от конвейера Boost , описанного выше. Вы создаете именованный сегмент с shm_open() и усечением с ftruncate(). Оттуда вы получите сопоставленный указатель на это выделенное пространство, вызвав mmap(). В более простых случаях, когда вы будете делиться только между родительскими и дочерними процессами, вы можете использовать этот пример кода с этого сайта .

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

0 голосов
/ 29 августа 2018

Конечно, другие программы не могут получить доступ к матрице, пока она находится в «нормальной» памяти процесса.

Не подвергая сомнению подход к проектированию: да, вы должны использовать разделяемую память. Функции поиска, такие как shmget (), shmat () и т. Д. Тогда вам не нужно передавать указатель на другую программу (которая на самом деле не будет работать), вы просто используете один и тот же файл в ftok () везде, чтобы получить доступ к разделяемая память.

...