共享内存中的队列起作用
Posted
技术标签:
【中文标题】共享内存中的队列起作用【英文标题】:Queue in shared memory acting up 【发布时间】:2011-12-12 23:43:42 【问题描述】:共享内存让我很难过,而 GDB 并没有多大帮助。我分配了 32KB 共享内存,我使用 shmat
将其转换为指向 struct
的指针,其中包含 A)bool
和 B)包含一个 std::string
、三个 @987654326 的对象队列@s 和一个 bool
,以及各种方法。 (我不知道这个套娃结构是不是你应该这样做,但这是我知道的唯一方法。使用消息队列不是一个选项,我需要使用多个进程。)
将一个对象推入队列是可行的,但是当我尝试推第二个对象时,程序会冻结。没有错误信息,什么都没有。这是什么原因造成的?我怀疑是内存不足,但如果是,我需要多少?
编辑:如果我不清楚 - 队列中的对象属于具有所描述的五个数据成员的类。
编辑 2: 我更改了队列条目的类,使其不使用 std::string
。 (很尴尬的是,我能够用一个原语来表示数据。)程序仍然在第二次 push() 时冻结。
编辑 3:我尝试在第一个 push()
之后立即从同一个队列中调用 front()
,并且 它 也冻结了程序。但是,检查队列外部的bool
的值工作正常,所以肯定是队列本身有问题。
编辑 4: 作为实验,我在用于共享内存的 struct
中添加了一个 std::queue<int>
。它表现出相同的行为——push()
工作了一次,然后front()
让它冻结。所以我用于队列项目的类也不是问题。
This 问题表明我不太可能用std::queue
解决这个问题。是这样吗?我应该像它说的那样使用boost
吗? (就我而言,我在父进程中执行shmget()
和shmat()
并试图让两个子进程进行通信,因此略有不同。)
编辑 5: 另一个子进程在调用 front()
时也会冻结。信号量确保在第一次 push()
调用之后发生这种情况。
【问题讨论】:
std::string
的内存分配在哪里?我赌两便士,这就是你的问题所在。
我们可以看到重现症状的最小、完整的代码吗?我们不知道您如何将 std::queue
放在共享内存上,如何使用信号量等。
【参考方案1】:
将std::string
对象放入共享内存段中可能不起作用。
它对于单个进程应该可以正常工作,但是一旦你尝试从第二个进程访问它,你就会得到垃圾:字符串将包含一个指向堆分配数据的指针,该指针是 仅在分配它的进程中有效。
我不知道你的程序为什么会死机,但想想也是完全毫无意义。
【讨论】:
【参考方案2】:正如我在评论中所说,您的问题源于尝试在结构中使用内部需要堆分配的对象,该结构应该是自包含的(即不需要进一步动态分配的内存)。
我会调整您的设置,并将 std::string 更改为某个固定大小的字符数组,例如
// this structure fits nicely into a typical cache line
struct Message
boost::array<char, 48> some_string;
int a, b, c;
bool c;
;
现在,当您需要在队列中发布内容时,将字符串内容复制到some_string
。当然,您应该适当调整字符串的大小(boost::array
可能不是最好的 - 理想情况下,您也需要一些长度信息)但您明白了...
【讨论】:
我想我理解内存分配的工作原理甚至不如我想象的那么好。 ^^;它确实看起来像一个公正的分析表明避免堆会减少我的misère-y。 (不过,您如何估计一个对象将占用的空间量?) 我在编辑评论为时已晚几分钟后发现了这一点。 -_- 我仍然无法让队列正常工作——std::queue
根本上是错误的工作工具吗?
@ShayGuy,是的,很可能在它下面使用std::deque
,它也进行自己的堆分配!您需要使用专门设计用于共享内存块的东西 - 看看 boost 进程间,它们具有适用于共享内存的容器包装器(和分配器)。以上是关于共享内存中的队列起作用的主要内容,如果未能解决你的问题,请参考以下文章