您当然可以使用 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() 联机帮助页,但这应该可以帮助您入门。需要记住的几点:
/All/ 对象使用的内存需要共享。例如,如果 Object 包含指向其他对象的指针或引用,或动态分配的成员(包括容器、std::string 等),则必须使用placement new 来创建所有内容(或至少所有需要与其他进程共享)在共享内存 blob 中。您不需要为每个对象创建一个新的 shm_open(),但是您必须(在创建过程中)跟踪它们的大小和偏移量,这在非平凡的情况下很容易出错,如果有的话,绝对会令人毛骨悚然花哨的自动分配类型,例如 STL 容器。
如果任何进程在对象被共享后会对其进行修改,则您需要提供单独的同步机制。这并不比你在多线程程序中做的更糟糕,但你必须考虑一下。
如果“客户端”进程不需要修改共享对象,您应该使用 O_RDONLY 而不是 O_RDWR 打开它们的句柄,并在没有 PROT_WRITE 权限标志的情况下调用 mmap()。如果客户端进程可能进行不需要与其他进程共享的本地修改,请使用 MAP_PRIVATE 而不是 MAP_SHARED 调用 mmap()。这将大大减少所需的同步量以及搞砸的风险。
如果这些进程将在多用户系统上运行和/或共享数据可能是敏感的和/或这是一个高可用性应用程序,那么您将需要比所示更复杂的访问控制更多。共享内存是安全漏洞的常见来源。