我有一个非常小的两个程序示例,一个用于编写共享内存段,另一个用于读取它。我发现std::string
(以及其他容器)存在潜在问题,所以尝试了boost::interprocess::string
boost::containers::string
。我很确定这是缺少一些非常基本和简单的东西,但看不到它!
在任何情况下,概要是当字符串很小(我认为虽然大于SSO)时,运行第一个程序会写入内存,第二个程序读取得非常好。但是,如果我使字符串非常大,如此处的示例那么读取程序段错误。如果读取和写入都在同一个进程中,但是功能不同(因此除了通过ipc之外不共享任何数据。 的 writeipc.cc
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <iostream>
#include <utility>
int main()
{
typedef boost::interprocess::string bi_string;
boost::interprocess::shared_memory_object::remove("Test");
boost::interprocess::managed_shared_memory managed_shm(boost::interprocess::create_only, "Test", 65536);
bi_string* i = managed_shm.construct<bi_string>("string")("abcdefghijklmnopqrstuvwxyzaskl;dfjaskldfjasldfjasdl;fkjwrotijuergonmdlkfsvmljjjjjjjjjjjjjj"); // make smaller (ie "jjjjjjjjjjjjjj" and test passes
std::cout << "inserting into shm" << *i << std::endl;
std::pair<bi_string*, size_t> q = managed_shm.find<bi_string>("string");
std::cout << *q.first << std::endl;
while(true)
std::cout << "still running"; // hack to keep process running (not required)
}
readipc.cc
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <iostream>
int main()
{
typedef boost::interprocess::string bi_string;
boost::interprocess::managed_shared_memory managed_shm(boost::interprocess::open_only, "Test");
std::pair<bi_string*, std::size_t> p = managed_shm.find<bi_string>("string");
std::cout << "existing value" << *p.first << std::endl;
}
答案 0 :(得分:3)
好的,答案是分配器相关的。
我发布了我认为是允许其他人快速了解如何开始使用IPC的答案。我发现很多关于网络的例子并没有很好地解释这个过程,并且给人的印象是使用普通的字符串等都可以,直到你从不同的过程中读取。因此,要完全实现解决方案,需要一些额外的小步骤。
实质上,您不能使用普通stl类型容器提供的分配器。记录在案here
这是分配到哪里的?
Boost.Interprocess容器放在共享内存/内存中 映射文件等......同时使用两种机制:
Boost.Interprocess construct<>, find_or_construct<>... functions. These functions place a C++ object in the shared memory/memory mapped
文件。但是这只放置了对象,而不是这个内存 对象可以动态分配。 共享内存分配器。这些允许分配共享内存/内存映射文件部分,以便容器可以分配 动态的内存片段来存储新插入的元素。
这意味着要放置任何Boost.Interprocess容器(包括 Boost.Interprocess字符串)在共享内存或内存映射文件中, 容器必须:
Define their template allocator parameter to a Boost.Interprocess allocator. Every container constructor must take the Boost.Interprocess allocator as parameter. You must use construct<>/find_or_construct<>... functions to place the container in the managed memory.
如果您执行前两个点,但不使用构造&lt;&gt;要么 find_or_construct&LT;&GT;你正在创建一个只放在你的容器中的容器 进程但是为共享的包含类型分配内存 内存/内存映射文件。
我创建了几个可以找到here
的示例函数上面缺少的是
namespace bi = boost::interprocess;
typedef bi::allocator<char, bi::managed_shared_memory::segment_manager> CharAllocator;
typedef bi::basic_string<char, std::char_traits<char>, CharAllocator> bi_string;
现在这是一个字符串,可以在我们为它获取分配器时存储。这意味着从内存段获取分配器,如此
bi::managed_shared_memory segment(bi::create_only, "shm name",
65536);
// Create an object of Type initialized to type
CharAllocator charallocator(segment.get_segment_manager());
现在charallocator可用于构造一个字符串类型,该字符串类型将在共享内存位置工作并能够正确读回。该字符串创建为:
bi_string str(charallocator);
然后你可以给它分配一个cstring。所以举个例子 std :: string test(“测试字符串”);
str = test.c_str();
如果您构建一个段,您的字符串将被存储
segment.construct<bi_string>("some name")(str)
您可以在共享内存存储中存储多个段。我希望这有助于其他人。代码在上面的链接中都可以通过测试获得。