简体   繁体   English

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

[英]Multi-processing with singletons C++ on Linux x86_64

For the following question, I am looking for an answer that is based on "pure" C/C++ fundamentals, so I would appreciate a non-Boost answer. 对于以下问题,我正在寻找基于“纯” C / C ++基本原理的答案,因此,我希望您能获得一个非Boost的答案。 Thanks. 谢谢。

I have an application (for example, a telecommunications infrastructure server) which will, when started, spawn several processes on a Linux environment (one for logging, one for Timer management, one for protocol messaging, one for message processing etc.). 我有一个应用程序(例如,电信基础结构服务器),该应用程序在启动时将在Linux环境上生成多个进程(一个用于日志记录,一个用于计时器管理,一个用于协议消息传递,一个用于消息处理等)。 It is on an x86_64 environment on Gentoo. 它位于Gentoo的x86_64环境中。 The thing is, I need a singleton to be able to be accessible from all the processes. 问题是,我需要一个单例才能从所有进程中进行访问。

This is different from multi-threading using say, POSIX threads, on Linux because the same address space is used by all POSIX threads, but that is not the case when multiple processes, generated by fork () function call, is used. 这与在Linux上使用POSIX线程的多线程不同,因为所有POSIX线程都使用相同的地址空间,但是当使用fork()函数调用生成的多个进程时,情况并非如此。 When the same address space is used, the singleton is just the same address in all the threads, and the problem is trivially solved (using the well known protections, which are old hat for everybody on SO). 当使用相同的地址空间时,单例只是所有线程中的相同地址,并且问题可以轻松解决(使用众所周知的保护,这对SO上的每个人都是旧帽子)。 I do enjoy the protections offered to me by multiple processes generated via fork(). 我确实喜欢通过fork()生成的多个进程为我提供的保护。

Going back to my problem, I feel like the correct way to approach this would be to create the singleton in shared memory, and then pass a handle to the shared memory into the calling tasks. 回到我的问题,我认为解决此问题的正确方法是在共享内存中创建单例,然后将共享内存的句柄传递给调用任务。

I imagine the following (SomeSingleton.h): 我想象以下内容(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.
     */
};

The getInstance() method returns the shared memory location for the SomeSingleton object. getInstance()方法返回SomeSingleton对象的共享内存位置。

My questions are as follows: 我的问题如下:

  1. Is this a legitimate way to handle the problem? 这是解决问题的合法方法吗? How have folks on SO handled this problem before? SO的人们以前是如何处理这个问题的?
  2. For the code above to work, I envision a global declaration (static by definition) that points to the shared memory as shown before the class declaration. 为了使上面的代码起作用,我设想了一个全局声明(按定义静态),该声明指向类声明之前显示的共享内存。
  3. Last, but not the least, I know that on Linux, the overheads of creating threads vs. processes is "relatively similar," but I was wondering why there is not much by way of multi-processing discussions on SO (gob loads of multi-threading, though!). 最后但并非最不重要的一点是,我知道在Linux上,创建线程与进程的开销“相对相似”,但是我想知道为什么在SO上没有太多的多处理讨论方式( -threading!)。 There isn't even a tag here! 这里甚至没有标签! Has multi-processing (using fork()) fallen off favors among the C++ coding community? 多处理(使用fork())是否在C ++编码社区中不受欢迎? Any insight on that is also appreciated. 任何对此的见解也将受到赞赏。 Also, may I request someone with a reputation > 1500 to create a tag "multi-processing?" 另外,我可以要求信誉> 1500的人创建标签“多处理”吗? Thanks. 谢谢。

If you create the shared memory region before forking, then it will be mapped at the same address in all peers. 如果在分叉之前创建共享内存区域,则它将在所有对等方中映射到相同的地址。

You can use a custom allocator to place contained objects inside the shared region also. 您也可以使用自定义分配器将包含的对象也放置在共享区域内。 This should probably be done before forking as well, but be careful of repetition of destructor calls (destructors that eg flush buffers are fine, but anything that makes an object unusable should be skipped, just leak and let the OS reclaim the memory after all processes close the shared memory handle). 这可能也应该在派生之前完成,但是要注意重复执行析构函数调用(析构函数,例如刷新缓冲区很好,但是应该跳过所有使对象不可用的事物,只是泄漏并让OS在所有进程之后回收内存关闭共享内存句柄)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM