我正在使用 SHM 块在多个 Linux 进程中共享数据。 当生产者将一些数据放入 SHM 时,它会通过 Posix-MQ 向消费者发送消息。该消息携带SHM的偏移量,消费者通过它可以准确地访问数据。
我担心存在内存顺序/障碍问题,就像我们在多线程模式中经常遇到的那样。 不同之处在于我们使用的是 Posix-MQ。里面有没有像STL中原子变量的
std::memory_order
操作那样的同步机制?
如果是这样,我不需要做任何特殊的威胁。
换句话说,在消费者看来,只要消费者收到了消息,数据就一定是ready/clean的。
虽然我已经在自己的程序中进行了测试,但我没有足够的信心让它进入我的生产代码中。
我的测试代码有点复杂,如果有人认为有必要我会粘贴在这里。 谢谢!
4.12 中的各种系统调用的列表,这些系统调用“相对于其他线程同步内存”(该术语本身并未在规范中定义)。 该列表包括明显的 pthread_*
和
sem_*
调用,但不包括
mq_*
。也就是说,在我看来,消息队列调用将充当适当的内存屏障是一个完全合理的假设。 我倾向于将 POSIX 解释为对系统具有全局可见影响的系统调用存在顺序一致性,因为我认为这是每个人在编写它时都会假设的。 因此,例如,如果您在一个进程中向文件写入一个字节,然后在另一个进程中读取它,那么这同样应该充当获取/释放对,并且在文件写入之前完成的任何共享内存访问在文件写入之后应该是全局可见的。文件读取。 我希望这同样适用于消息队列。
在更实际的层面上,在我看来,实现必须包含适当的障碍,以便
mq_*
功能本身能够正确运行,因此您也可以从中受益。如果您想格外小心,可以在
mq_send
之前添加
atomic_thread_fence(memory_order_release)
,在
mq_recv
后添加
atomic_thread_fence(memory_order_acquire)
。 与消息队列操作本身的成本相比,开销应该可以忽略不计。在像 x86 这样的强有序系统上,根本没有任何开销。 在那里,正常的加载和存储已经具有获取/释放语义,因此栅栏不会发出任何屏障指令。 它仅充当编译器屏障,并且由于
mq_*
系统调用函数可能对编译器来说是不透明的,因此无论如何它都不会重新排序它们周围的内存访问。