boost.interprocess:managed_shared_memory和managed_external_buffer之间是否不兼容?

时间:2019-10-16 18:35:29

标签: boost boost-interprocess

Boost.interprocess具有四种不同类型的托管内存:managed_shared_memorymanaged_mapped_filemanaged_heap_memorymanaged_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;
}

0 个答案:

没有答案