共享记忆:让我们谈谈它的特殊性

Shared memory : Let's talk about its specificity

本文关键字:特殊性 我们 记忆 共享      更新时间:2023-10-16

让我们考虑两个进程P1P2之间的以下伪代码:
在进程 P1 中:

struct SharedStruct
{
int i;
void *pData;
};
HANDLE hMapFile = CreateFileMapping("Global\MyFileMappingObject")  
LPCTSTR pBuf = (LPTSTR) MapViewOfFile(hMapFile, ...) 
SharedStruct mySharedStruct;
mySharedStruct.i=33;
mySharedStruct.pData = (void*) calloc (1, 10);
memcpy ( (void*) pBuf, (void*) (&mySharedStruct), sizeof (mySharedStruct));  

在进程 P2 中:

hMapFile hMapFile = OpenFileMapping("Global\MyFileMappingObject")  
SharedStruct *pSharedStruct_P2 = (SharedStruct *) MapViewOfFile (hMapFile,...)
...  

问题:
pSharedStruct_P2->pDataP2无法使用的本地 P1 内存地址

反思:
共享记忆的使用是否仅限于基本类型(int,float,...(? 还是共享记忆的另一种用途来支持本地地址的共享?

可以使用偏移量而不是常规指针来存储对其他对象的引用。例如,代替这个:

struct Foo {
double a;
double b;
double* a_or_b;
};
Foo x{1, 2, nullptr};
x.a_or_b = &a;

您可以这样做:

struct Foo {
double  a;
double  b;
ptrdiff_t a_or_b;
};
Foo x{1, 2, 0};
x.a_or_b = static_cast<const char*>(&a) - static_cast<const char*>(&a_or_b);

如您所见,它比使用常规指针要繁琐得多!顺便说一下,偏移变量和原始变量不需要像这样在同一个结构中,这只是为了让示例更简单......它们只需要位于同一个映射内存块中。

boost.interprocess中有一些容器,沿着std::string和std::map的行,在内部工作。它们的存在正是为了让您在这种情况下使用它们。该库还有许多其他有用的工具,用于操作共享内存,您可能希望使用这些工具,例如用于映射共享内存和进程间互斥锁的独立于平台的 API。

其他具有这种偏移形式的库是FlatBuffers和Cap'n Proto。在这些情况下,内部使用偏移量的动机略有不同(这样磁盘或网络上的序列化与内存中表示形式完全相同(,但它仍然可以很好地用于共享内存。