共享记忆:让我们谈谈它的特殊性
Shared memory : Let's talk about its specificity
让我们考虑两个进程P1和P2之间的以下伪代码:
在进程 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->pData是P2无法使用的本地 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。在这些情况下,内部使用偏移量的动机略有不同(这样磁盘或网络上的序列化与内存中表示形式完全相同(,但它仍然可以很好地用于共享内存。
相关文章:
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 我们可以访问一个不存在的联盟的成员吗
- 如果编译的源代码是特定于它编译的硬件的,我们如何分发它
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- 如何在C++中读取空格分隔的输入 当我们不知道输入的数量时
- C++:考虑但不调用构造函数的特殊性
- 我们可以删除链表中静态内存中的节点吗
- 为什么我们要为avl树实现返回一个指向节点的指针,而不是void函数
- 当我们从/tp地址中添加/减去一个整数时会发生什么
- 当我们为(;;) 写作时,它做了什么?for 循环中的双分号有什么作用?
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 我们可以将数据永久保存为数据结构吗?
- 为什么我们将单个或多维数组的大小声明为常量值?
- 为什么我们不能重复使用具有不同模板参数的别名模板标识符?
- 为什么当我们有常量引用时创建临时对象?
- 为什么我们再次从结构对象创建结构变量?
- 为什么我们不编写可以处理C++标识符的汇编器和链接器?
- 当返回类型声明为 ListNode 时,我们是否可以返回 false<T>*
- 共享记忆:让我们谈谈它的特殊性