Boost.interprocess имеет четыре различных типа управляемой памяти: managed_shared_memory
, managed_mapped_file
, managed_heap_memory
и managed_external_buffer
. Бустерная документация, хотя это явно не указано, указывает на то, что они должны взаимодействовать друг с другом. Учитывая, что все четыре наследуют от 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
.
Не верно ли мое предположение о совместимости? В расширенной документации есть пример кода, в котором заполняется сегмент 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;
}