在Linux x86_64上使用单例C ++进行多处理

时间:2012-03-15 21:11:00

标签: c++ linux singleton fork

对于以下问题,我正在寻找一个基于“纯”C / C ++基础知识的答案,所以我希望得到一个非Boost答案。感谢。

我有一个应用程序(例如,电信基础设施服务器),它在启动时会在Linux环境中产生多个进程(一个用于记录,一个用于定时器管理,一个用于协议消息传递,一个用于消息处理等)。 )。它位于Gentoo上的x86_64环境中。问题是,我需要一个单例才能从所有进程中访问。

这与在Linux上使用POSIX线程的多线程不同,因为所有POSIX线程都使用相同的地址空间,但是当使用fork()函数调用生成的多个进程时则不是这种情况。 。当使用相同的地址空间时,单例在所有线程中只是相同的地址,并且问题很容易解决(使用众所周知的保护,对于SO上的每个人都是老套的)。我喜欢通过fork()生成的多个进程提供给我的保护。

回到我的问题,我觉得接近这个问题的正确方法是在共享内存中创建单例,然后将句柄传递给共享内存到调用任务中。

我想象以下(SomeSingleton.h):

#include <unistd.h>
#... <usual includes>
#include "SomeGiantObject.h"

int size = 8192; // Enough to contain the SomeSingleton object
int shm_fd = shm_open ("/some_singleton_shm", O_CREAT | O_EXCL | O_RDWR, 0666);
ftruncate (shm_fd, size);
sharedMemoryLocationForSomeSingleton = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

class SomeSingleton
{
   public:
     SomeSingleton* getInstance ()
     {
        return reinterpret_cast<SomeSingleton*>sharedMemoryLocationForSomeSingleton;
     }
   private:
     SomeSingleton();
     /*
        Whole bunch of attributes that is shared across processes.
        These attributes also should be in shared memory.
        e.g., in the following
        SomeGiantObject* obj;
        obj should also be in shared memory.
     */
};

getInstance()方法返回SomeSingleton对象的共享内存位置。

我的问题如下:

  1. 这是处理问题的合法方式吗? SO之前的人们如何处理这个问题?
  2. 为了使上面的代码工作,我设想了一个全局声明(定义为静态),指向在类声明之前显示的共享内存。
  3. 最后,但并非最不重要,我知道在Linux上,创建线程与进程的开销“相对类似”,但我想知道为什么SO上的多处理讨论没有多少(gob)但是,多线程的负载!)。这里甚至没有标签!在C ++编码社区中,多处理(使用fork())是否有利?对此的任何见解也表示赞赏。另外,我可以请求有声誉的人吗? 1500创建标签“多处理?”感谢。

1 个答案:

答案 0 :(得分:1)

如果在分叉之前创建共享内存区域,那么它将映射到所有对等体中的相同地址。

您也可以使用自定义分配器将包含的对象放在共享区域内。这也许应该在分叉之前完成,但是要小心重复析构函数调用(例如,刷新缓冲区很好的析构函数,但是应该跳过使对象不可用的任何东西,只是泄漏并让OS在所有进程之后回收内存关闭共享内存句柄。)