【问题标题】:Shared memory in LinuxLinux 中的共享内存
【发布时间】:2025-12-11 00:35:01
【问题描述】:

我想以不同进程可以访问相同静态数据的方式实现类:

class Shared()
{
public:
    static int GetValue();
    static void SetValue(int value);
};

如何使用共享内存来存储内部数据。谁能帮我做到这一点?任何答案将不胜感激。

【问题讨论】:

    标签: c++ linux static shared-memory


    【解决方案1】:

    示例代码如下所示,这是一个非常基本的实现。课程将解释如何创建、设置/获取单个值和销毁共享内存。可以使用模板将错误检查、通知等添加为策略类。

    #include <iostream>
    #include <stdexcept>
    #include <stdio.h>
    #include <sys/ipc.h>
    #include <sys/types.h>
    #include <sys/shm.h>
    #include <string.h>
    
    template <key_t KEY, typename T, int COUNT = 1>
    class Shm
    {
    
    public:
      Shm():shm_(0)
      {
        get();
        attach();
      }
    
      ~Shm()
      {
        if(shm_ != NULL)
        {
          shmdt(shm_);
          shm_ = 0;
        }
      }
    
      //Set one element 
      void SetValue(const T* data, int count = 1)
      {
        if(sizeof(T)*count > sizeof(T) * COUNT)
        {
          throw std::runtime_error("Data size greater than shm size");
        }
        memcpy(shm_, data, sizeof(T)*count);
      }
    
      //Get pointer to element
      const T* GetValue()
      {
        T* ptr = new(shm_) T;
        return ptr;
      }
    
    
      static void create()
      {
        if ((shmid_ = shmget(KEY, COUNT*sizeof(T), IPC_CREAT | 0666)) < 0) 
        {
          throw std::runtime_error("Failed create shm");
        }
      }
      static void destroy()
      {
        get();
        if(shmctl(shmid_, IPC_RMID, NULL)<0)
        {
        perror("shctl");
        throw std::runtime_error("Error cannot remove shared memory");
        }
          shmid_ = -1;
      }
    
    private:
      static void get()
      {
        if(shmid_ == -1)
        {
          if((shmid_ = shmget(KEY, COUNT*sizeof(T), 0666)) < 0)
          {
        perror("shmget");
        throw std::runtime_error("Shared memory not created");
          }
        }
    
      }
    
      void attach()
      {
        if ((shm_ = shmat(shmid_, NULL, 0)) == (char *) -1) 
        {
        throw std::runtime_error("Failed attach shm");
        }
      }
      void* shm_;
      static int shmid_;
    };
    
    
    template <key_t KEY, typename T, int COUNT> 
    int Shm<KEY, T, COUNT>::shmid_ = -1;
    
    int main(int argc, char ** argv)
    {
      if(argc == 2)
      {
        if(std::string(argv[1]) == "server")
        {
          int val = 50;
          Shm<0x1234, int>::create(); 
          Shm<0x1234, int> shm;
          shm.SetValue(&val);
        }
        else if(std::string(argv[1]) == "client")
        {
          Shm<0x1234, int> shm;
          const int* ptr = shm.GetValue();
          std::cout <<"Val = " << *ptr <<std::endl;
          Shm<0x1234, int>::destroy(); 
        }
      }
      else
      {
        std::cerr<<"Usage shm [server][client]"<<std::endl;
      }
    
      return 0;
    }
    

    【讨论】:

      【解决方案2】:

      您真的不想为此手动推出解决方案(特别是如果它必须是可移植的),但幸运的是 boost::interprocess 将为共享内存提供此类功能和更多功能(例如分配器)。

      最小示例(未经测试):

      #include <boost/interprocess/managed_shared_memory.hpp>
      using namespace boost::interprocess;
      
      void* allocate(size_t bytes)
      {
          static managed_shared_memory segment(create_only, "MySharedMemory", 65536);
          return segment.allocate(bytes);
      }
      

      【讨论】: