boost的进程间段管理器分配器本身是否可以与其他进程共享? [英] Can boost's interprocess segment manager allocators be themselves shared with other processes?

查看:106
本文介绍了boost的进程间段管理器分配器本身是否可以与其他进程共享?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用boost :: interprocess创建一个共享的进程间映射. 为此,我从映射所在的共享内存段的segment_manager创建一个分配器.

I am creating a shared interprocess map using boost::interprocess. For this I create an allocator from the segment_manager of the shared memory segment where the map is located.

映射的元素值类型是basic_string,其本身已模板化以使用从同一段管理器创建的char分配器. 在一个过程中,我创建地图,在另一个过程中,我使用该过程中的maps迭代器搜索一个项目,在某些情况下,我使用迭代器调用map :: erase.

The element value type of the map is a basic_string which is itself templated to use a char allocator created from the same segment manager. In one process I create the map and in the other I search for an item using the maps iterator in that process and in some cases I call map::erase with the iterator.

这会导致访问冲突异常,我知道我正在使用有效的迭代器进行呼叫. 访问冲突发生在对basic_string的析构函数的调用中,该析构函数是迭代器指向的"pair"的"second". 当我在插入后立即在写入过程中使用迭代器执行相同的擦除操作时,没有访问冲突.

This causes an access violation exception and I know that I am making the call with a valid iterator. The access violation occurs in the call to the destructor of the basic_string that is the 'second' of the 'pair' pointed to by the iterator. When I perform the same erase operation using an iterator in the writing process immediately after insertion there is no access violation.

似乎读取过程正在尝试使用元素的分配器释放元素的内存,该分配器是在写入过程中创建的,而该分配器仅在创建它的过程中有效.

It looks as though the reading process is trying to release the memory of the element using the element's allocator, which was created in the writing process whereas that allocator is only valid in the process that created it.

这是否意味着分配器本身无法共享?

Does this mean that the allocators themselves cannot be shared?

我希望分配器在两个进程中都可以使用,因为它的状态应该只包含在两个进程中都有效的相对指针. 如果没有,如何共享在进程之间使用共享内存(堆)分配的元素? 在将这些分配器传递给basic_string元素之前,是否应该在编写过程中以特殊的方式创建这些分配器,以允许我在其他进程的anerase操作中使用它们?

I would have expected that allocator to be usable in both processes as its state should contain only relative pointers that are valid in both processes. If not, how can I share elements that use shared memory (heap) allocations between processes? Should I have created those allocators in a special way in the writing process before passing them to the basic_string elements to allow me to use them in anerase operation in another process?

还有什么可能导致访问冲突?

What else might be causing the access violation?

推荐答案

分配器很好(魔术在offset_ptr中,并且在进程边界之间是透明的).

The allocators are fine (the magic is in offset_ptr and it's transparent across process boundaries).

如果客户端"破坏了字符串,则说明您正在做除读取之外的其他事情.您很可能会收到一份副本,例如:

If the "client" destructs strings, then you're doing something else than reading. Most likely, you're receiving a copy, like:

auto by_copy = smap.find(key)->second; // makes a copy

尝试,例如做

auto const& by_ref = smap.find(key)->second; // doesn't copy

或者,您可能正在执行smap[key],如果没有密钥,它将自动分配.这可能会导致老式的竞争状况(进程之间共享数据就像在线程之间共享数据:您需要适当的同步).

Alternatively you might be doing smap[key] which automatically allocates if the key wasn't there. This could cause an old-fashioned race condition (sharing data between processes is much like sharing data between threads: you need proper synchronization).

最后,您没有提到密钥的/anything/,但是如果它也是一个字符串,那么仅按键查找就很容易从共享内存中分配(而且,它是临时的,会破坏).种族状况再次迫在眉睫.另请参阅有效克服Boost.Interprocess共享内存中映射中的关键类型之间的不匹配

Lastly, you didn't mention /anything/ about the key, but if it, too, is a string then just the lookup-by-key is prone to allocate from shared memory (and, it being a temporary, it would destruct). The race condition looms again. See also want to efficiently overcome mismatch between key types in a map in Boost.Interprocess shared memory

在没有适当的 SSCCE

In the absence of a proper SSCCE or MCVE, let me throw one at you. You might spot something you do differently.

#include <iostream>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/map.hpp>

namespace bip = boost::interprocess;

namespace shared {
    namespace bc  = boost::container;

    using Segment = bip::managed_shared_memory;
    using Manager = Segment::segment_manager;
    template <typename T>
    using Alloc   = bc::scoped_allocator_adaptor<bip::allocator<T, Manager> >;

    using String  = bip::basic_string<char, std::char_traits<char>, Alloc<char> >;
    template <typename K, typename V, typename Cmp = std::less<K> >
        using Map = bip::map<K, V, Cmp, Alloc<std::pair<K const, V> > >;
};

int main() {
    using namespace shared;

    Segment smt(bip::open_or_create, "de06c60a-0b80-4b20-a805-b3f405f35427", 20ul<<20); // 20 mb
    auto& mat = *smt.find_or_construct<Map<String, String> >("dict")(smt.get_segment_manager());

    if (mat.empty()) {
        mat.emplace("1", "one");
        mat.emplace("2", "two");
        mat.emplace("3", "three");
    } else {
        // shared string factory
        auto ss = [&](auto... stuff) { return String(stuff..., smt.get_segment_manager()); };

        auto  copy = mat.at(ss("3")); // constructs and destructs temp String("3"); constructs copy
        auto& ref  = mat.at(ss("2")); // constructs and destructs temp String("2"); no copy
        std::cout << "copy: " << copy << "\n";
        std::cout << "ref: "  << ref  << "\n";

        // iterate with no shared temps or copies:
        for (auto& p : mat)
            std::cout << "entry '" << p.first << "' -> '" << p.second << "'\n";
    } // destructs copy
}

与Coliru相同,但带有内存映射文件(因为那里不允许共享内存):

The same on Coliru, but with memory-mapped files (because shared memory is not allowed on there):

在Coliru上直播

using Segment = bip::managed_mapped_file;

不打印任何内容,先运行,再运行:

Prints nothing first run, subsequent runs:

copy: three
ref: two
entry '1' -> 'one'
entry '2' -> 'two'
entry '3' -> 'three'

这篇关于boost的进程间段管理器分配器本身是否可以与其他进程共享?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆