加速进程间:管理共享内存错误
Boost Interprocess: managed shared memory errors
我正在使用boosts进程间库在多个程序之间共享内存。 3 或 4 个其他程序将在 cust_order 中读取和写入共享内存内容。对内存空间的访问需要序列化。
在下面的示例程序中,引擎循环访问risk_queue的内容,如果已填充,则获取第一个cust_order编号并定位该顺序进行处理。
-
在每个程序使用的 objects.h 头文件中:
struct cust_order { int ID; char CLID[128]; int CUST_ID; char ORDER_STATUS; }; cust_order o; boost::interprocess::managed_shared_memory cust_order_segment(boost::interprocess::open_or_create, "cust_order", 65536 * 100); typedef int cust_order_KeyType; typedef cust_order cust_order_MappedType; typedef std::pair<const int, cust_order> cust_order_ValueType; typedef boost::interprocess::allocator< cust_order_ValueType, boost::interprocess::managed_shared_memory::segment_manager> cust_order_ShmemAllocator; typedef boost::interprocess::map<cust_order_KeyType, cust_order_MappedType, std::less<cust_order_KeyType>, cust_order_ShmemAllocator> cust_order_MySHMMap; cust_order_MySHMMap::iterator cust_order_iter; boost::interprocess::managed_shared_memory risk_queue_segment(boost::interprocess::open_or_create, "risk_queue", 65536 * 100); typedef int risk_queue_KeyType; typedef int risk_queue_MappedType; typedef std::pair<const int, int> risk_queue_ValueType; typedef boost::interprocess::allocator< risk_queue_ValueType, boost::interprocess::managed_shared_memory::segment_manager> risk_queue_ShmemAllocator; typedef boost::interprocess::map<risk_queue_KeyType, risk_queue_MappedType, std::less<risk_queue_KeyType>, risk_queue_ShmemAllocator> risk_queue_MySHMMap; risk_queue_MySHMMap::iterator risk_queue_iter;
-
在引擎中.cpp:
int main() { risk_queue_ShmemAllocator risk_queue_alloc_inst( risk_queue_segment.get_segment_manager()); cust_order_ShmemAllocator cust_order_alloc_inst( cust_order_segment.get_segment_manager()); for (; 0 < 1;) { boost::interprocess::offset_ptr<risk_queue_MySHMMap> risk_queue_m_pmap = risk_queue_segment.find<risk_queue_MySHMMap>("risk_queue").first; boost::interprocess::offset_ptr<cust_order_MySHMMap> cust_order_m_pmap = cust_order_segment.find<cust_order_MySHMMap>("cust_order").first; risk_queue_iter = risk_queue_m_pmap->begin(); if (risk_queue_iter != risk_queue_m_pmap->end()) { ordid = risk_queue_iter->second; cust_order_m_pmap->find(ordid)->second = o; o.ORDER_STATUS = '0'; o = cust_order_m_pmap->find(ordid)->second; risk_queue_m_pmap->erase(ordid); } }; return 0; }
这是我在程序完美运行几秒钟后遇到的错误:
engine: /usr/include/boost/intrusive/bstree.hpp:1331: boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::iterator boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::insert_unique_commit(boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::reference, const insert_commit_data&) [with ValueTraits = boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::pair<const int, event>, boost::interprocess::offset_ptr<void>, (boost::container::tree_type_enum)0, true>, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::dft_tag, 3>; VoidOrKeyOfValue = void; VoidOrKeyComp = boost::container::value_to_node_compare<boost::container::container_detail::tree_node<std::pair<const int, event>, boost::interprocess::offset_ptr<void>, (boost::container::tree_type_enum)0, true>, boost::intrusive::tree_value_compare<boost::interprocess::offset_ptr<std::pair<const int, event>, long int, long unsigned int, 0>, std::less<int>, boost::container::container_detail::select1st<int>, false> >; SizeType = long unsigned int; bool ConstantTimeSize = true; boost::intrusive::algo_types AlgoType = (boost::intrusive::algo_types)5; HeaderHolder = void; boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::iterator = boost::intrusive::tree_iterator<boost::intrusive::bhtraits<boost::container::container_detail::tree_node<std::pair<const int, event>, boost::interprocess::offset_ptr<void>, (boost::container::tree_type_enum)0, true>, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::dft_tag, 3>, false>; boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::reference = boost::container::container_detail::tree_node<std::pair<const int, event>, boost::interprocess::offset_ptr<void>, (boost::container::tree_type_enum)0, true>&; boost::intrusive::bstree_impl<ValueTraits, VoidOrKeyOfValue, VoidOrKeyComp, SizeType, ConstantTimeSize, AlgoType, HeaderHolder>::insert_commit_data = boost::intrusive::insert_commit_data_t<boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void> >, long int, long unsigned int, 0> >]: Assertion `( p == this->end() || !this->comp()(*p, value) )' failed.
Aborted (core dumped)
请您帮助我了解错误。让我知道,如果有更好的方法来做我需要做的事情。
好的,所以我查看了你的代码。你自己说的:
对内存空间的访问需要序列化。
那么,你为什么不呢?
笔记
简化标头:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/map.hpp>
struct cust_order {
int ID;
char CLID[128];
int CUST_ID;
char ORDER_STATUS;
};
namespace bip = boost::interprocess;
namespace Shared {
using Segment = bip::managed_shared_memory;
using Manager = Segment::segment_manager;
template <typename T> using Alloc = bip::allocator<T, Manager>;
template <typename K, typename V, typename Cmp = std::less<K> >
using Map = bip::map<K, V, Cmp, Alloc<typename bip::map<K, V>::value_type> >;
}
using OrderTable = Shared::Map<int, cust_order>;
using RiskQueue = Shared::Map<int, int>;
简化主要:
int main() {
Shared::Segment cust_order_segment(bip::open_or_create, "cust_order", 65536 * 100);
Shared::Segment risk_queue_segment(bip::open_or_create, "risk_queue", 65536 * 100);
auto risk_queue = risk_queue_segment.find_or_construct<RiskQueue>("risk_queue")(risk_queue_segment.get_segment_manager());
auto order_table = cust_order_segment.find_or_construct<OrderTable>("cust_order")(cust_order_segment.get_segment_manager());
while (true) {
while (!risk_queue->empty()) {
auto it = risk_queue->begin();
auto ordid = it->second;
order_table->at(ordid).ORDER_STATUS = '0';
risk_queue->erase(ordid);
}
}
}
最值得注意的事情:
- 没有任何同步(段管理器中的一些细节除外(
- 您没有检查任何错误(缺少段、缺少对象、缺少从risk_queue引用的顺序(
- 为什么数据结构位于单独的段中?
- 为什么你在紧密循环中运行,就好像你在处理无锁数据结构一样?
- 你为什么要滥用地图,就好像它们是优先级队列一样?界面与预期用途不匹配
最有趣的是,由于
RiskQueue
按键排序,并被视为队列,因此我们必须假设键类型表示风险/优先级。映射的类型显然是订单 ID,它指的是客户订单表。目前为止,一切都好。
但是,你这样做了
risk_queue->erase(ordid);
这完全令人困惑,因为这将订单 ID 视为"风险队列"的关键?队列没有键,我们刚刚得出结论,风险的"键"表示优先级(所以它不是订单 ID(。
即使猜测它应该被
order_table->erase(ordid)
,也没有多大意义,因为那样在删除之前设置订单状态的目的是什么。我只能得出结论,该行是一个错误,需要
risk_queue->erase(it);
当然,在处理完同步之前,这些都不重要。
如果您有许多订单处理客户端,我建议您改用信号量。一切都将变得更加安全,并且减少CPU功率的浪费。
如果您确实必须具有无锁数据访问,请确保数据结构实际上是无锁的,并确保保持一致性(这是一个难题,因为您决定将数据拆分为两个结构(。
相关文章:
- 使用Boost Interprocess创建托管共享内存需要很长时间
- 字符串共享内存映射的向量
- CUDA 使用共享内存平铺 3D 卷积实现
- 共享内存:MapViewOfFile 返回错误 5
- 如何在多写入器情况下对文件支持的共享内存中的大页面出错
- 有没有办法列出所有共享内存对象的名称?
- 共享内存的升压容器是否实现锁定?
- 共享内存中的健壮互斥锁不是那么健壮
- 使用IPC/共享内存将Integer数组从C++传递到Python
- 共享内存和性能
- 在这种特殊情况下,我是否需要在共享内存中使用原子类型
- 是否可以在专用内存空间中分配一个为提升管理共享内存而创建的对象
- fork(),在C中共享内存和指针
- 访问共享内存而不使用易失性、std::atomic、信号量、互斥锁和自旋锁
- 提升进程间共享内存open_or_create每次都会引发异常
- 通过 mmap-ed 共享内存传递可变长度 C 字符串
- 越界访问 CUDA 共享内存
- 在共享内存中插入映射映射时出现编译器错误
- 矩阵矢量产品 CUDA 通过平铺和共享内存提高性能
- 如何更改在 c++ 中使用提升库创建的共享内存的路径