【问题标题】:Writing a binary archive into a shared memory with BOOST::serialization使用 BOOST::serialization 将二进制存档写入共享内存
【发布时间】:2020-11-10 23:53:59
【问题描述】:

我目前正在尝试使用 BOOST 库将数据作为二进制存档序列化到共享内存段中。 我使用 text_oarchive() 方法成功实现了该功能,如下所示。现在我想使用 binary_oarchive() 方法而不是 text_oarchive() 方法。

shared_memory_object::remove("shm");
shared_memory_object shm(create_only, "shm", read_write);

shm.truncate(sizeof(UnSerData)); // 10MiB
mapped_region region(shm, read_write);

bufferstream bs(std::ios::out);
bs.buffer(reinterpret_cast<char*>(region.get_address()), region.get_size());

boost::archive::text_oarchive oa(bs);

oa << UnSerData;

在实现 binary_oarchive() 方法时,它失败了: 错误:重载“binary_oarchive(boost::interprocess::bufferstream&)”的调用不明确 boost::archive::binary_oarchive oa(bs);

shared_memory_object::remove("shm");
shared_memory_object shm(create_only, "shm", read_write);

shm.truncate(sizeof(UnSerData)); // 10MiB
mapped_region region(shm, read_write);

bufferstream bs(std::ios::out);
bs.buffer(reinterpret_cast<char*>(region.get_address()), region.get_size());

boost::archive::binary_oarchive oa(bs);

oa << UnSerData;

我只是不确定应该为 binary_oarchive() 方法使用哪种缓冲区 我已经尝试过 ostream 但无法让它工作。 已经谢谢了。

编辑: JSON 数据如下所示:

{
  "name": "UMGR",
  "description": "UpdateManager",
  "dlt_id": "1234",
  "log_mode": ["kConsole"],
  "log_level": "kVerbose",
  "log_dir_path": "",
  "ipc_port": 33,
  "reconnection_retry_offset": 0,
  "msg_buf_size": 1000
}

这是一个非常简单的数据示例,并且会变得更加复杂。 我使用 RapidJSON 将数据解析为来自 RapidJSON 的文档对象。然后数据被解析成如下所示的结构:

typedef struct{
    string name;
    string description;
    string dlt_id;
    string log_mode;
    string log_level;
    string log_dir_path;
    uint ipc_port;
    uint reconnection_retry_offset;
    uint msg_buf_size;
    int checksum;

//function for serializing the struct
template <typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
    ar & name;
    ar & description;
    ar & dlt_id;
    ar & log_mode;
    ar & log_level;
    ar & log_dir_path;
    ar & ipc_port;
    ar & reconnection_retry_offset;
    ar & msg_buf_size;
    ar & checksum;
}
} UMGR_s;

这可能不是解析 JSON 数据最“有效”的方式,但降低解释器速度本身不是我的目标,而是优化整个系统。 由于我正在将此方法与我也使用此 JSON 解析器实现的当前尝试进行比较,因此结果应该仍然有意义。

我还考虑过使用内存映射而不是共享内存实现。因为守护程序无论如何都必须打开文件(带有序列化数据)并将其传递给进程。所以也许让接收进程通过 boost 库中的内存映射实现来收集数据会更有效。

【问题讨论】:

    标签: c++ serialization boost


    【解决方案1】:

    我无法重现您描述的错误:

    Compiling On Coliru

    使用文件映射让我们甚至可以在 COLIRU 上运行它:

    Live On Coliru

    打印

    00000000: 3232 2073 6572 6961 6c69 7a61 7469 6f6e  22 serialization
    00000010: 3a3a 6172 6368 6976 6520 3137 2030 2030  ::archive 17 0 0
    00000020: 0a00 0000 0000 0000 0000 0000 0000 0000  ................
    00000030: 0000 0000 0000 0000 0000 0000 0000 0000  ................
    *
    000027f0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
    

    想法

    回到盒子里

    由于您使用共享内存,可能出于某种原因,您不想跳过序列化的整个步骤吗?

    根据您的数据,这可能非常简单,或者需要一些工作。

    如果您的 Data 类型是 POD,那将非常简单 (TM)。在这种情况下,您可以将副本存储在 size(UnSerData) 的映射区域中(并且只有这样)。

    如果您的类型使用内部指针或分配,我建议改为managed_shared_memory。 BIP 分配器使用offset_ptr,它在共享内存区域中使用是安全的,随后您不需要序列化(只需同步)即可从其他进程访问。

    我在这个网站上有很多使用managed_shared_memory 和allocator/scoped_allocator_adaptor 的例子,如果你想看看的话,它们的复杂程度各不相同。

    【讨论】:

    • 哇,非常感谢您的详细回答。目标是减小数据(UnSerData)的大小。数据在系统初始启动时从 JSON 文件解释。在解释和序列化 JSON 文件后,数据应通过 SHM 分发到进程。关闭系统时,序列化数据存储到文件中。当系统现在重新启动时,从文件中读取序列化数据并通过 SHM 分发到进程。因此,解释器的工作已经消失,并且文件读取速度更快,因为它比初始 JSON 文件小。
    • 是的。听起来你应该更清楚地遵循一个目标。当你(反)序列化时,数据被复制和解释都是一样的。如果您可以向我展示数据的实际外观,我可以提供帮助。但也请阅读此similar question。
    • 编辑了我的初始问题。
    • 编辑:shared memory approach。使用 online execution 的映射文件。
    • 哇,非常感谢您的努力。社区应该为有像你这样的人感到自豪>:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 2016-11-25
    • 1970-01-01
    相关资源
    最近更新 更多