我有一个非常复杂的类(它内部有unordered_map等等),我想用两个我的进程共享它的一个对象。我可以简单地将指针从一个进程传递到另一个进程吗?我想,不,但希望听到“是的!”。
如果“不”,我将很高兴看到任何链接如何应对这种情况。 我需要为所有进程只有一个这个对象的实例,因为它非常大,并且所有进程都可以用于只读。
答案 0 :(得分:13)
您当然可以使用IPC来实现这一目标,并且有很多情况下多个进程比多线程进程更有意义(至少有一个进程是基于遗留代码构建的,您无法对其进行大量修改,他们最好用不同的语言编写,你需要尽量减少一个过程中出现故障的可能性,影响其他人的稳定性等。)在兼容POSIX的环境中,你会做的
int descriptor = shm_open("/unique_name_here", O_RDWR | O_CREAT, 0777);
if (descriptor < 0) {
/* handle error */
} else {
ftruncate(descriptor, sizeof(Object));
void *ptr = mmap(NULL, sizeof(Object), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, descriptor, 0);
if (!ptr || ptr == MAP_FAILED)
/* handle error */ ;
Object *obj = new (ptr) Object(arguments);
}
在一个过程中,然后
int descriptor = shm_open("/the_same_name_here", O_RDWR | O_CREAT, 0777);
if (descriptor < 0) {
/* handle error */
} else {
Object *obj = (Object *) mmap(NULL, sizeof(Object), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, descriptor, 0);
if (!obj || obj == MAP_FAILED)
/* handle error */ ;
}
在另一个。还有很多选项,当你完成后我没有显示清理代码,所以你仍然应该阅读shm_open()和mmap()联机帮助页,但这应该让你开始。要记住的一些事情:
/需要共享对象使用的所有内存。例如,如果Object包含指向其他对象的引用或引用,或动态分配的成员(包括容器,std :: string等),则必须使用placement new来创建所有内容(或者至少包含所有内容)需要与共享内存blob中的其他进程共享)。你不需要为每个对象提供一个新的shm_open(),但你必须跟踪(在创建过程中)它们的大小和偏移量,这在非平凡的情况下可能容易出错,如果你有花哨的自动分配类型,如STL容器。
如果任何进程在共享后修改对象,则需要提供单独的同步机制。这并不比你在多线程程序中所做的更糟糕,但你必须考虑它。
如果“客户端”进程不需要修改共享对象,则应该使用O_RDONLY而不是O_RDWR打开其句柄,并在没有PROT_WRITE权限标志的情况下调用mmap()。如果客户端进程可能进行不需要与其他进程共享的本地修改,则使用MAP_PRIVATE而不是MAP_SHARED调用mmap()。这将大大减少所需的同步量以及将其搞砸的风险。
如果这些进程将在多用户系统上运行和/或共享数据可能是敏感的和/或这是一个高可用性应用程序,那么您将需要比显示的更复杂的访问控制以上。共享内存是安全漏洞的常见来源。
答案 1 :(得分:5)
不,进程不会(自然)共享内存。如果是一个选项,那么你可以查看Boost.Interprocess以便于内存共享。
答案 2 :(得分:4)
不,指针对其他进程毫无意义。操作系统为其他进程创建单独的地址空间;默认情况下,他们不知道其他进程正在运行,甚至不可能这样做。
答案 3 :(得分:0)
这里的诀窍是内存必须在你的两个进程中以相同的方式映射。如果你的映射共享内存可以这样安排,它会起作用,但我敢打赌它会非常困难。
还有其他一些可能性。第一个是使用数组;数组索引将跨两个进程工作。
您还可以使用placement new确保在共享内存中的已知位置分配对象,并使用这些偏移量。
答案 4 :(得分:0)
如果您使用的是Linux,则可以使用共享内存在进程之间存储公共数据。一般情况下,请查看boost IPC库。
但是来自一个进程的指针不能在另一个进程中使用(如果访问IO或某些特殊设备,则可以使用它的地址)
答案 5 :(得分:0)
如果您使用Qt4,那么QSharedMemory或者您可以使用套接字和自定义序列化协议。