共享内存中的队列起作用

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 进程间,它们具有适用于共享内存的容器包装器(和分配器)。

以上是关于共享内存中的队列起作用的主要内容,如果未能解决你的问题,请参考以下文章

共享内存的访问控制不起作用?

用信号量保护共享内存段不起作用

linux 进程间通信——内存共享映射mmap和munmap

了解多处理:Python 中的共享内存管理、锁和队列

检查linux中消息队列和共享内存状态的命令?

如何在python和C / C ++中使用共享内存