c++ - 使用 boost::interprocess::shared_ptr 共享生命周期跨进程

标签 c++ boost shared-ptr boost-interprocess

我正在尝试使用 boost::interprocess 以便在进程之间共享数据并利用 shared_ptr 进行生命周期管理。我有一个驻留在共享内存中的 map ,应该有两个进程访问它。

    boost::shared_ptr<boost::interprocess::managed_mapped_file> segment =
          boost::make_shared<boost::interprocess::managed_mapped_file>
                 (boost::interprocess::open_or_create,
                  "./some-mmap.txt", //file name
                  65536);           //segment size in bytes

    pair_allocator_type alloc_inst(segment->get_segment_manager());

    elements = boost::interprocess::make_managed_shared_ptr(
            segment->find_or_construct<map_type>("elements")
            (std::less<IdType>(), alloc_inst),
            *segment
    );

在我的测试程序中,父进程和子进程基本上都使用上面的代码。因此,它们使用相同的底层文件、相同的共享对象名称(“元素”)、相同的类型等。

但是,我注意到每当一个子进程死亡时,集合的大小就会下降到 0。奇怪。我调查了一下,它似乎与 elements 的破坏有关(当这个共享指针超出范围时)。每当 elements 超出范围时,基础集合的大小就会变为 0。

我还看到 elements 在父进程和子进程中都有 use_count 恰好 1。对于 Parent 来说这是有道理的,但我不明白为什么 Child 会这样。我的假设是,当 Child 进程死亡时,use_count 下降到 0,然后集合被清除。

我想要的是当子进程死亡时,指向的对象( map )不会被销毁。我不应该假设哪些进程是事件的,哪些不是。

  • 我是否以错误的方式初始化了 boost::interprocess::shared_ptr
  • 我是否完全遗漏了该指针的语义 --> 它是否仅用于管理共享内存对象生命周期在一个进程内而不是跨进程?
  • 如何让 shared_ptr 的 use_count 跨进程共享?

编辑 - 收集说明

elements 是一个 boost::interprocess::map,它将特定的 IdType 映射到指向 的共享内存共享指针>内存类型。当子进程结束时,elements 的大小降为 0。

typedef boost::interprocess::managed_mapped_file::segment_manager segment_manager_type;
typedef std::pair<const IdType, ShmemType::pointer_type> pair_type;
typedef boost::interprocess::allocator<pair_type, segment_manager_type> pair_allocator_type;
typedef boost::interprocess::map<IdType, ShmemType::pointer_type, std::less<IdType>, pair_allocator_type> map_type;

编辑 - 来自 boost 文档的示例

我从 boost 文档中获取了示例并对其进行了扩展,以找出我最初问题的根本原因。

#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/smart_ptr/shared_ptr.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <string>
#include <cstdlib> //std::system

using namespace boost::interprocess;

typedef allocator<int, managed_mapped_file::segment_manager>  ShmemAllocator;
typedef vector<int, ShmemAllocator> MyVector;

#include <iostream>

//Main function. For parent process argc == 1, for child process argc == 2
int main(int argc, char *argv[])
{
   if(argc == 1){ //Parent process

      //Create a new segment with given name and size
       managed_mapped_file segment(open_or_create, "./a_MySharedMemory.txt", 65536);

      //Initialize shared memory STL-compatible allocator
      const ShmemAllocator alloc_inst (segment.get_segment_manager());

//      MyVector* elements = segment.find_or_construct<MyVector>("some-vector")      //object name
//                      (alloc_inst);
       typedef boost::interprocess::managed_shared_ptr<MyVector, boost::interprocess::managed_mapped_file>::type map_pointer_type;

        map_pointer_type elements = boost::interprocess::make_managed_shared_ptr(
                segment.find_or_construct<MyVector>("some-vector")      //object name
                (alloc_inst),
                segment
        );

      for(int i = 0; i < 100; ++i)  //Insert data in the vector
          elements->push_back(i);

      std::cout << elements->size() << std::endl;
        std::cout << elements->at(0) << std::endl;
        std::cout << elements->at(30) << std::endl;

      //Launch child process
      std::string s(argv[0]); s += " child ";
      if(0 != std::system(s.c_str()))
         return 1;

      std::cout << elements->size() << std::endl;
      std::cout << elements->at(0) << std::endl;
      std::cout << elements->at(30) << std::endl;

   }
   else{ //Child process
      //Open the managed segment
       managed_mapped_file segment(open_only, "./a_MySharedMemory.txt");
       const ShmemAllocator alloc_inst (segment.get_segment_manager());

       typedef boost::interprocess::managed_shared_ptr<MyVector, boost::interprocess::managed_mapped_file>::type map_pointer_type;

       map_pointer_type elements = boost::interprocess::make_managed_shared_ptr(
            segment.find_or_construct<MyVector>("some-vector")      //object name
            (alloc_inst),
            segment
    );

//       MyVector* elements = segment.find_or_construct<MyVector>("some-vector")      //object name
//                      (alloc_inst);

      //Use vector in reverse order
      std::sort(elements->rbegin(), elements->rend());

   }

   return 0;
}

在这种情况下,在子进程死亡后, vector 在父进程中的大小 == 0。如果我使用原始指针 (MyVector* elements = segment.find_or_construct...),则可以在父进程中按预期使用该集合。

所以我对共享指针的行为还是有疑问的

最佳答案

  • 问: 我是否以错误的方式初始化了 boost::interprocess::shared_ptr

你做得对。不过,您不需要共享指针中的段。只需确保该段比任何进程间 shared_ptrs(或者,就此而言,任何对共享内存段的引用)的生命周期都长。

  • 问: 我是否完全遗漏了这个指针的语义 --> 它是否仅用于管理一个进程内的共享内存对象生命周期,而不是跨进程?

没有。

  • 问: 如何让 shared_ptruse_count 跨进程共享?

文档:make_managed_shared_ptr :

Returns an instance of a shared pointer constructed with the default allocator and deleter from a pointer of type T that has been allocated in the passed managed segment.

other page明确提到(强调我的):

Since the reference count and other auxiliary data needed by shared_ptr must be created also in the managed segment, and the deleter has to delete the object from the segment, the user must specify an allocator object and a deleter object when constructing a non-empty instance of shared_ptr

关于c++ - 使用 boost::interprocess::shared_ptr 共享生命周期跨进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30505817/

相关文章:

python - boost python : passing large data structure to python

c++ - 调用 boost io_service.post 的正确方法

c++ - 如何查看io_service中的任务是否完成?

c++ - 为什么 shared_ptr 删除器必须是 CopyConstructible 的?

c++ - enable_shared_from_this : Sharing the use count in member

c++ - GLFW 无法在 Mavericks 上获得 OpenGL 4.1 上下文

c++ - if 语句表达式调用函数,需要测试是否为真

c++ - 如何为 Unix 创建 makefile

c++ - shared_ptr<const A> 到 shared_pointer<A>

c++ - 多线程之间的互斥锁