Межпроцессное взаимодействие с общей памятью - PullRequest
3 голосов
/ 29 ноября 2011

Я выделил блок разделяемой памяти, используя shmget.

Затем я присоединяю общую память к процессу A и процессу B соответственно, используя shmat. Я предполагаю, что дескрипторы (то есть адреса в пределах A и B, которые сопоставлены с фактической общей памятью) для A и B, возвращаемых shmat, отличаются.

Давайте предположим, что маркеры для A и B определены как char* p и char* q соответственно. У меня вопрос: если мы запишем объект по адресу p + sizeof(anotherObject) в процессе A, можем ли мы ожидать получить тот же объект по адресу q + sizeof(anotherObject) в процессе B?

Полагаю, это так, но я не уверен на 100%. Если да, то как достигается этот механизм связи или отображения, поскольку мы знаем, что p + sizeof(anotherObject) и q + sizeof(anotherObject) относятся к разным ячейкам памяти?

Ответы [ 2 ]

4 голосов
/ 30 ноября 2011

Современные процессоры используют виртуальные адресные пространства.Адрес, который вы используете в своей программе, не является «реальным» адресом объектов, операционная система и процессор отображают страницы памяти в диапазон адресов, и вы используете его как «память».

Создание общей памяти просто означает, что ОС отображает одну и ту же страницу памяти в адресном пространстве двух или более разных процессов.Тот факт, что два указателя в двух процессах не имеют одинаковое числовое значение, ничего не значит, даже если указатели в разных процессах имеют одинаковое числовое значение, они обычно указывают на разные области памяти.

О написании "объект "в память", вы должны сначала "сериализовать" его.Я упоминал, что указатели в разных процессах несовместимы друг с другом.Если у вашего объекта есть какие-либо члены-указатели или другие объекты, которые могут содержать указатели, вы должны придумать способ заменить эти указатели фактическими данными, потому что, как только вы читаете объект из другого потока, эти указатели так же хороши, какtrash.

Помните, что в C ++ std :: sting, std :: vector и других контейнерах вместе с любым виртуальным объектом (объектом, имеющим виртуальную функцию) есть указатели внутри.поэтому, если вы хотите передать строку, вам нужно записать ее как последовательность символов в общую память и прочитать то же самое на другой стороне.

0 голосов
/ 29 ноября 2011

Можете ли вы записать двоичное представление объекта в области общей памяти? Да.

Можете ли вы безопасно использовать объект из другой программы, получая доступ к его двоичному представлению, хранящемуся в общей памяти? Иногда, но не в целом.

Правила аналогичны записи двоичного представления для сериализации на диск или по проводам. Вы должны убедиться, что обрабатываете указатели на другие объекты, а также на все элементы, не являющиеся POD. Например, экземпляр std::string имеет указатель на выделенную память, который:

  1. может не находиться в области общей памяти
  2. может не иметь того же адреса в другом процессе (например, данные находятся в общей памяти, но области общей памяти были сопоставлены с разными базовыми адресами в обоих процессах).

Итак, простая эвристика заключается в том, что если X - это то, что вы не можете:

std::ofstream file("foo.bin",std::ios::binary);
file.write(reinterpret_cast<const char*>(&X), sizeof(X));

Тогда вы не сможете безопасно записать его в общую память.

Примечания : даже если данные относятся к типу POD, вы не можете предполагать, что их запись безопасна. В некоторых операционных системах можно запускать несколько разных типов процессов (например, 32-разрядные и 64-разрядные процессы). В таком случае использование типов, таких как int, может не совпадать в обоих процессах. Учитывая конкретную операционную систему, конкретный компилятор и конкретные параметры компиляции, может быть возможно найти надежный способ написания таких типов POD. Если это окружение может измениться, избегайте этого, как чумы.

...