Boost.interprocess具有四种不同类型的托管内存:managed_shared_memory
,managed_mapped_file
,managed_heap_memory
和managed_external_buffer
。 boost文档虽然没有明确说明,但确实表明它们应该可以互操作。鉴于所有四个继承自ipcdetail::basic_managed_memory_impl
,这似乎是合理的假设。
以下代码创建一个managed_shared_memory
对象,将其填充,然后将文件对象重新映射为manage_mapped_file
并验证内容。这按预期工作得很好,因为两者本质上是在做同一件事(将文件映射到内存中)。
然后关闭所有内容,并将文件对象的内容读取到本地缓冲区中,然后该缓冲区用于创建managed_external_buffer
对象。尝试在托管内存上调用find()
方法将导致SEGV。
当我使用mutex_family
代替null_mutex_family
时,将发生挂起而不是SEGV。 strace
表示它正在futex(..., FUTEX_WAIT_PRIVATE, ...)
通话中。
在调试会话中,从find()
方法退出,我发现offset_ptr
的偏移量很差,这导致了SEGV。使用managed_mapped_file
时显然不会发生这种情况。
我对互操作性的假设不正确吗? boost文档中有一个代码示例,其中填充了managed_heap_memory
段,然后随后将其内容的副本作为managed_external_buffer
使用。这是否意味着在托管内存类型之间存在一些互操作限制?
// gcc-7.3.0
// boost-1.68
#include <iostream>
#include <fstream>
#include <string>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/managed_external_buffer.hpp>
using std::cout;
using std::endl;
using namespace boost::interprocess;
namespace ipc {
// standardize implementations
using msm = basic_managed_shared_memory< char, rbtree_best_fit<null_mutex_family, offset_ptr<void>>, iset_index>;
using mmf = basic_managed_mapped_file< char, rbtree_best_fit<null_mutex_family, offset_ptr<void>>, iset_index>;
using meb = basic_managed_external_buffer<char, rbtree_best_fit<null_mutex_family, offset_ptr<void>>, iset_index>;
}
int main () {
struct shm_remover {
shm_remover () { shared_memory_object::remove("__myint__"); }
~shm_remover () { shared_memory_object::remove("__myint__"); }
} remover;
{
cout << "original:" << endl;
ipc::msm original(create_only, "__myint__", 1024);
int *i0 = original.construct<int>("my_int")(42);
cout << " *i0=" << *i0 << endl;
// map in shared file that was just created
// exact path is OS specific: /dev/shm for linux
cout << "mapped_file:" << endl;
ipc::mmf managed_mapped_file(open_read_only, "/dev/shm/__myint__");
const int *i1 = (managed_mapped_file.find<int>("my_int")).first;
cout << " *i1=" << *i1 << endl;
}
// copy contents of shared file to local buffer
std::ifstream file("/dev/shm/__myint__", std::ios::binary);
std::string buffer(1024, '\0');
file.read(&buffer[0], 1024);
file.close();
cout << "external_buffer:" << endl;
ipc::meb managed_external_buffer(open_only, static_cast<void *>(&buffer[0]), 1024);
// SEGV here
auto result = managed_external_buffer.find<int>("my_int");
cout << " after find()" << endl;
const int *i2 = result.first;
cout << " *i2=" << *i2 << endl;
return 0;
}