【问题标题】:Allocating a user defined struct in shared memory with boost::interprocess使用 boost::interprocess 在共享内存中分配用户定义的结构
【发布时间】:2018-04-05 13:36:26
【问题描述】:

我正在尝试使用boost::interprocess 在共享内存中分配一个非常简单的数据结构,但我无法完全弄清楚如何使用boost interprocess allocators 在我分配为的共享内存段中执行内存分配/解除分配关注

using namespace boost::interprocess;
shared_memory_object::remove("MySharedMem");
mSharedMemory = std::make_unique<managed_shared_memory>(
    open_or_create, "MySharedMem", 65536);

我之前问过类似的question,但不幸的是我从来没有得到任何答案。下面的MyStruct 本质上是一个数组,其长度字段指示数组的大小。现在我有一个简单的长度字段,但稍后我会添加一些其他构造函数参数(布尔值和其他简单类型)。

为了在共享内存段中分配它,我知道我必须对分配器做一些事情,但我找不到一个类似的例子,我有一个包含数组/指针字段的用户定义类型。

    using MyType = struct MyType {
        explicit MyType(const size_t aSize)
            : mSize(aSize)
            , mpData(new char[aSize])
        {}

        ~MyType() {
            delete[]mpData;
        }
        size_t mSize;
        char * mpData;
    };

    using MyTypeAllocator = boost::interprocess::allocator<MyType,
        boost::interprocess::managed_shared_memory::segment_manager>;

    // Initialize the shared memory STL-compatible allocator
    MyTypeAllocator alloc(mSharedMemory->get_segment_manager());

【问题讨论】:

  • 你需要教MyType 也使用分配器而不是使用operator new
  • @T.C.谢谢,关于我如何做到这一点的任何指示?我一直在寻找一些简单的例子。使用 int 或 uint32_t 非常简单,因为它们很简单,带有指针字段的结构的问题是 sizeof() 很有趣,因为它不考虑也需要存储的分配字节的大小。我认为这与 boost::interprocess 世界中的节点有关,但我对此很陌生。

标签: c++ c++11 boost shared-memory boost-interprocess


【解决方案1】:

只是不要进行手动分配。如果您想要连续分配 char 类型的 aSize 元素,这就是 C++ 的 std::vector 的用途。

最重要的是,std::vector 已经知道如何使用另一个分配器,所以真的没有理由不使用它:

template <typename Alloc>
struct MyType {
    explicit MyType(size_t aSize, Alloc alloc = {}) : mData(aSize, alloc) {}

  private:
    std::vector<char, Alloc> mData;
};

现在要与标准库构造/作用域分配器一起使用,您可能需要定义 allocator_type 嵌套类型:

    using allocator_type = Alloc; // typename Alloc::template rebind<char>::other;

就是这样。只需将其用作任何具有分配器的标准库类型即可:

int main() {
    using namespace Shared;

    Shared::remove("MySharedMem");
    auto memory = Segment(create_only, "MySharedMem", 65536);

    using A = Alloc<char>;
    A alloc(memory.get_segment_manager());

    auto* data = memory.find_or_construct<MyType<A>>("data")(1024, memory.get_segment_manager());

    return data? 0 : 255;
}

为了可维护性,我在 Shared 命名空间中创建了一些方便的 typedef。这是完整的示例

完整样本

Live On Coliru ¹

#include <boost/interprocess/managed_shared_memory.hpp>
#include <vector>

template <typename Alloc>
struct MyType {
    using allocator_type = typename Alloc::template rebind<char>::other;

    explicit MyType(size_t aSize, Alloc alloc = {}) : mData(aSize, alloc) {}

  private:
    std::vector<char, Alloc> mData;
};

namespace Shared {
    namespace bip = boost::interprocess;

    using Segment = bip::managed_shared_memory;
    using Manager = Segment::segment_manager;
    template <typename T> 
        using Alloc = bip::allocator<T, Manager>;

    void remove(char const* name) { bip::shared_memory_object::remove(name); }

    using bip::create_only;
}

int main() {
    using namespace Shared;

    Shared::remove("MySharedMem");
    auto memory = Segment(create_only, "MySharedMem", 65536);

    using A = Alloc<char>;
    A alloc(memory.get_segment_manager());

    auto* data = memory.find_or_construct<MyType<A>>("data")(1024, memory.get_segment_manager());

    return data? 0 : 255;
}

¹Coliru 使用托管映射文件,因为那里不支持共享内存

【讨论】:

  • 一如既往的好答案,但是否可以向 MyType 添加一些额外的简单成员并将它们也存储在共享内存中,例如MyType 除了 aSize 参数外,还采用 bool、uint64_t 和可能的字符串。前两个额外的参数具有微不足道的分配器,并且有关于使用自定义分配器的 shm_string 类型的很好示例,我不确定如何正确保存 MyType 并随后从共享内存中恢复。
  • 当然。 POD 数据在 [共享] 内存中永远不是问题
  • 在你的示例程序的背后有很多事情发生,我首先试图理解它:“使用 allocator_type = typename Alloc::template rebind::other” 非常令人困惑并且似乎没有必要(我认为重新绑定与容器内的节点分配有关,我在 VS 中注释掉了这行代码,它仍然有效),另外,使用 A = Alloc - 什么是 参数用于?这似乎扩展到 boost::interprocess::allocator.
  • 然后我们用'memory.get_segment_manager()'构造alloc——我认为它应该是一个'int'参数,但是get_segment_manager()返回一个'segment_manager *',它不完全是一个int。
  • 关于嵌套的typedef,我特地说了我添加它的目的。随意忽略。
猜你喜欢
  • 2012-11-05
  • 2012-11-26
  • 2020-10-19
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 2015-02-14
  • 1970-01-01
  • 2014-11-30
相关资源
最近更新 更多