共享内存进程间通信

时间:2011-11-29 16:44:58

标签: c++ c memory-management ipc

我使用shmget分配了一块共享内存。

然后我使用shmat分别将共享内存附加到进程A和进程B.我假设shmat返回的A和B的句柄(即A和B中映射到实际共享内存的地址)是不同的。

我们假设A和B的句柄分别定义为char* pchar* q。 我的问题是,如果我们将一个对象写入进程A中的地址p + sizeof(anotherObject),我们是否可以期望在进程B中的地址q + sizeof(anotherObject)处获得相同的对象?

我猜是这样的,但我不是100%肯定。如果是这样,那么如何实现这种通信或映射机制,因为我们知道p + sizeof(anotherObject)q + sizeof(anotherObject)指的是不同的内存位置?

2 个答案:

答案 0 :(得分:4)

现代处理器使用虚拟地址空间。您在程序中使用的地址不是对象的“真实”地址,操作系统和处理器将内存页面映射到地址范围,您将其用作“内存”。

创建共享内存只是意味着操作系统将同一个内存页面映射到两个或多个不同进程的地址空间。事实上两个进程中的两个指针没有相同的数值意味着什么,即使不同进程中的指针具有相同的数值,它们通常指向不同的内存位置。

关于将“对象”写入内存,首先必须“序列化”它。我提到不同进程中的指针彼此不兼容。如果你的对象有任何指针成员或其他可能包含指针的对象,你必须想出一种用实际数据替换这些指针的方法,因为一旦你从另一个线程读取对象,那些指针就像垃圾桶。

请注意,C ++ std :: sting,std :: vector和其他容器以及任何虚拟对象(具有虚函数的对象)都有指针。所以如果你想传递一个字符串,你需要把它作为一个字符序列写入共享内存,并在另一边读取相同的方法。

答案 1 :(得分:0)

您可以在共享内存区域中编写对象的二进制表示吗?是。

通过访问存储在共享内存中的二进制表示,可以安全地使用另一个程序中的对象吗?有时,但不是一般。

规则类似于将序列化的二进制表示写入磁盘或通过线路。您必须确保处理指向其他对象以及所有非POD成员的指针。例如,std::string实例有一个指向已分配内存的指针:

  1. 可能不在共享内存区域
  2. 在其他进程中可能没有相同的地址(例如,数据在共享内存中,但共享内存区域映射到两个进程中的不同基址)。
  3. 所以,一个简单的启发式方法是,如果X是你可以做的任何事情:

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

    然后你无法安全地将其写入共享内存。

    备注:即使数据是POD类型,您也不能认为将其写出是安全的。在某些操作系统上,可以运行几种不同类型的进程(例如32位和64位进程)。在这种情况下,使用int等类型在两个进程中可能不同。给定特定的操作系统,特定的编译器和特定的编译设置,可能有可能获得编写此类POD类型的可靠方法。如果这种环境可以改变,那就像瘟疫一样避免这样做。