我想使用CreateFileMapping() windows API函数在共享内存中创建一个std::vector。我知道如何创建和管理共享内存,但如何将std::vector分配到内存中的固定地址?我无法使用boost或其他库,我使用的是CBuilder++ 2010。我认为可能使用的一个变体是
CreateFileMapping()
std::vector
boost
std::vector<int> myVec; myVec *mv; mv = shared_memory_addr ?
但是,如何检测向量的真实的大小来调整内存大小呢?
zf2sa74q1#
我会使用Boost.Interprocess,它解释了如何做到这一点:http://www.boost.org/doc/libs/1_38_0/doc/html/interprocess/quick_guide.html#interprocess.quick_guide.qg_interprocess_container注意这里没有使用std::vector<>,std::vector<>不适合共享内存使用,因为它通常是用三个指针(开始、end、capacity或一些等价的指针)来实现的,并且地址在进程之间会有所不同,所以Boost.Interprocess有自己的vector类,这是专门为您要做的事情而构建的。
std::vector<>
0pizxfdo2#
请记住,您需要同步对向量的任何访问(除非您只需要读访问)-std::vector通常不是线程安全的,并且不声明其任何成员volatile,这使得在编译器作用域之外的同时访问(就像在共享内存区域中发生的那样)非常危险。...毕竟,我不会这么做共享内存是一个非常低级、非常棘手的概念,它并不适合std::vector这样的高级数据容器,在一种语言中(截至cpp 03),它没有为并发问题提供良好的内置解决方案,也没有意识到类似共享内存的东西的存在。......它甚至可能触发未定义的行为:虽然std::vector通常使用其allocator来为其元素获取存储空间,但(据我所知)允许分配更多的内存(即用于内部目的,无论是什么)使用X1 M6 N1 X或任何其它分配策略(我认为微软的std::vector实现在调试版本中做到了这一点)...这些指针只对内存Map的一侧有效。为了避免std::vector,我只需要在Map范围中预先分配足够的内存,并使用一个简单的计数器来保存有效元素的数量,这应该是安全的。
volatile
allocator
cyej8jka3#
您需要实现自己的分配器来实现这一点。分配器是一个std::vector<>模板参数。
ttisahbt4#
使用placement new在共享内存中构造一个向量。你还需要一个向量的分配器,这样它就可以使用共享内存来存储它的元素。如果向量只是存储int,并且你可以把共享内存部分放在每个进程的同一个虚拟地址,这可能会起作用。
zpjtge225#
你可以使用共享内存,Map到一个 * 固定地址 *,也就是说,地址在每个进程中都是相同的,允许使用原始指针。因此,如果您执行以下操作,就可以拥有(多个)共享内存区域:
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> struct MySegment { static const size_t alloc_size = 1048576; static const void *getAddr() { return (void *)0x400000000LL; } static const char *getSegmentName() { return "MySegment"; } }; template <typename MemorySegment> class SharedMemory { public: typedef boost::interprocess::fixed_managed_shared_memory shared_memory_t; typedef shared_memory_t::segment_manager segment_manager_t; static shared_memory_t *getSegment() { if (!segment) { assert(MemorySegment::getAddr() != 0 && "want a fixed address for all processes"); segment = new boost::interprocess::managed_shared_memory( boost::interprocess::open_or_create, MemorySegment::getSegmentName(), MemorySegment::alloc_size, MemorySegment::getAddr()); } return segment; } static segment_manager_t *getSegmentManager() { return getSegment()->get_segment_manager(); } private: static boost::interprocess::managed_shared_memory *segment; }; template <typename MemorySegment> typename SharedMemory<MemorySegment>::shared_memory_t *SharedMemory<MemorySegment>::segment = NULL; template <class MemorySegment, class T> class SharedMemoryAllocator { public: typedef boost::interprocess::allocator<T, typename SharedMemory<MemorySegment>::segment_manager_t> InterprocessAllocator; // Delegate all calls to an instance of InterprocessAllocator, pointer allocate(size_type n, const void *hint = 0) { return TempAllocator().allocate(n, hint); } void deallocate(const pointer &p, size_type n) { return TempAllocator().deallocate(p, n); } size_type max_size() const { return TempAllocator().max_size(); } void construct(const pointer &ptr, const_reference v) { return TempAllocator().construct(ptr, v); } void destroy(const pointer &ptr) { return TempAllocator().destroy(ptr); } typedef typename InterprocessAllocator::value_type value_type; typedef typename InterprocessAllocator::pointer pointer; typedef typename InterprocessAllocator::reference reference; typedef typename InterprocessAllocator::const_pointer const_pointer; typedef typename InterprocessAllocator::const_reference const_reference; typedef typename InterprocessAllocator::size_type size_type; typedef typename InterprocessAllocator::difference_type difference_type; SharedMemoryAllocator() {} template <class U> SharedMemoryAllocator(const SharedMemoryAllocator<MemorySegment, U> &u) {} template <typename OtherT> struct rebind { typedef SharedMemoryAllocator<MemorySegment, OtherT> other; }; private: static InterprocessAllocator TempAllocator() { return InterprocessAllocator(SharedMemory<MemorySegment>::getSegmentManager()); } };
然后,您可以用途:
std::vector<int, SharedMemoryAllocator<MySegment, int> vec;
向量的元素将被放入共享内存(当然,vec也必须被分配到那里)。
vec
5条答案
按热度按时间zf2sa74q1#
我会使用Boost.Interprocess,它解释了如何做到这一点:http://www.boost.org/doc/libs/1_38_0/doc/html/interprocess/quick_guide.html#interprocess.quick_guide.qg_interprocess_container
注意这里没有使用
std::vector<>
,std::vector<>
不适合共享内存使用,因为它通常是用三个指针(开始、end、capacity或一些等价的指针)来实现的,并且地址在进程之间会有所不同,所以Boost.Interprocess有自己的vector类,这是专门为您要做的事情而构建的。0pizxfdo2#
std::vector
示例,并使用自定义分配器使向量也将其数据放置在共享内存中。请记住,您需要同步对向量的任何访问(除非您只需要读访问)-
std::vector
通常不是线程安全的,并且不声明其任何成员volatile
,这使得在编译器作用域之外的同时访问(就像在共享内存区域中发生的那样)非常危险。...毕竟,我不会这么做共享内存是一个非常低级、非常棘手的概念,它并不适合
std::vector
这样的高级数据容器,在一种语言中(截至cpp 03),它没有为并发问题提供良好的内置解决方案,也没有意识到类似共享内存的东西的存在。......它甚至可能触发未定义的行为:虽然
std::vector
通常使用其allocator
来为其元素获取存储空间,但(据我所知)允许分配更多的内存(即用于内部目的,无论是什么)使用X1 M6 N1 X或任何其它分配策略(我认为微软的std::vector
实现在调试版本中做到了这一点)...这些指针只对内存Map的一侧有效。为了避免
std::vector
,我只需要在Map范围中预先分配足够的内存,并使用一个简单的计数器来保存有效元素的数量,这应该是安全的。cyej8jka3#
您需要实现自己的分配器来实现这一点。分配器是一个
std::vector<>
模板参数。ttisahbt4#
使用placement new在共享内存中构造一个向量。你还需要一个向量的分配器,这样它就可以使用共享内存来存储它的元素。如果向量只是存储int,并且你可以把共享内存部分放在每个进程的同一个虚拟地址,这可能会起作用。
zpjtge225#
你可以使用共享内存,Map到一个 * 固定地址 *,也就是说,地址在每个进程中都是相同的,允许使用原始指针。
因此,如果您执行以下操作,就可以拥有(多个)共享内存区域:
然后,您可以用途:
向量的元素将被放入共享内存(当然,
vec
也必须被分配到那里)。