IPC通过共享内存与atomic_t; 它对x86有用吗?

Met*_*est 10 c c++ linux gcc c++11

我有以下代码通过共享内存进行进程间通信.一个进程写入日志,另一个进程从中读取.一种方法是使用信号量,但在这里我使用的是atomic_t类型的原子标志(log_flag),它位于共享内存中.日志(log_data)也是共享的.

现在问题是,这适用于x86架构还是需要信号量或互斥量?如果我使log_flag非原子化怎么办?鉴于x86具有严格的内存模型和主动缓存一致性,并且优化不适用于指针,我认为它仍然有用吗?

编辑:请注意,我有一个8核的多核处理器,所以我在这里忙等待没有任何问题!

// Process 1 calls this function
void write_log( void * data, size_t size )
{
    while( *log_flag )
           ;
    memcpy( log_data, data, size );
    *log_flag = 1;
}

// Process 2 calls this function
void read_log( void * data, size_t size )
{
    while( !( *log_flag ) )
       ;
    memcpy( data, log_data, size );
    *log_flag = 0;
}
Run Code Online (Sandbox Code Playgroud)

Fab*_*llo 2

我不建议这样做,原因有两个:首先,虽然编译器可能不会优化指针访问,但这并不意味着处理器不会缓存指向的值。其次,它是原子的这一事实不会阻止 while 循环末尾和 *log_flag=0 行之间的读取访问。互斥锁更安全,但速度要慢得多。

如果您使用 pthreads,请考虑使用 RW 互斥体来保护整个缓冲区,这样您就不需要标志来控制它,互斥体本身就是标志,并且在频繁读取时您将获得更好的性能。

我也不建议执行空 while() 循环,这样会占用所有处理器。在循环内放入 usleep(1000) 以使处理器有喘息的机会。

  • @Jeff:你能详细说明一下吗?我不明白如何导致 100% CPU 利用率并完全用完您的预定时间片*每次在等待期间*,从而降低进程的优先级应该是“利用 MP 系统”。 (5认同)
  • 繁忙的等待并不像你想象的那么糟糕。特别是如果您有一个多处理器系统并且想要利用它。 (4认同)
  • @NiklasBaumstark:如果您知道您不会等待很长时间的资源,那么繁忙的等待可以节省您上下文切换和等待再次调度的开销。如果在单处理器系统上它不会很好地工作(因为无论如何你都必须上下文切换)。它们有它们的用途,您只需要注意哪些资源受到保护以及系统架构即可。 (4认同)