c++ - mmap 和 mutex 的使用

标签 c++ linux multithreading

我是 Linux 的新手,所以我有几个关于使用 mmap 和线程的问题。

在 Linux 中,互斥量是否会导致上下文切换?我做了谷歌,有些人说是,有些人说不是。因此,关键部分更好吗?我将只使用一个进程。

所以,我是用户端,我映射了一些硬件寄存器。我的代码基本上是这样的:

setRegisterBits(  offset, fromBit, toBit )
{
   ReadRegister()
   ModifyRegister()
   WriteRegister()

}

许多线程可以访问同一个 mmap,所以我需要这个函数是原子的。 Linux 程序员会提出什么建议?

最佳答案

Is it so that in Linux a mutex will cause a context switch?

Linux 互斥量是使用 futex 实现的:

Futex operation is entirely user space for the non-contended case. The kernel is involved only to arbitrate the contended case. As any sane design will strive for non-contention, futexes are also optimized for this situation.

换句话说,当一个互斥体被锁定时,线程上下文切换到内核,被放入 futex 等待队列并从 CPU 中取消调度,因此停止前进(阻塞,另一个上下文切换)。


Therefore is a critical section better?

在 Windows 上 CRITICAL_SECTION本质上是一个进程内互斥体。

在 Linux 上,有 pthread_mutex_t ( http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_init.html ) 和 std::mutex它是 pthread_mutex_t 的包装器。 pthread_mutex_t 是通用的,无论是用于进程内还是进程外(不同进程的线程之间)同步,它的工作方式都是一样的。 std::mutex 不提供进程外功能。

不过,更一般地说,critical section is a block of code which only one thread can enter at one time .

还有pthread_spinlock_t在 Linux 上,它也可用于进程内或进程外同步。它不会取消进程的调度,但是,必须注意仅在可能的最短时间内锁定它,以便等待线程不会浪费 CPU 忙于它。


I am user side and I have mmaped some HW registers. I have code which is basically like [...] Many threads could access the same mmap and so I need this function to be atomic. What would a Linux programmer suggest?

它是许多生产者,单一消费者的场景。答案取决于您的优化目标、预期的竞争程度、执行 setRegisterBits 所需的时间以及它是否可以阻塞。

如果 setRegisterBits 阻塞,那么非阻塞同步原语将是一个糟糕的选择,因为这会在等待该线程解除阻塞并退出 setRegisterBits 时无缘无故地浪费其他线程的 CPU 周期 临界区。

开始的默认选择是 pthread_mutex_t。对它如何适用于您的工作负载进行基准测试。

现代 Linux 在现代 x86_64 硬件上的调度延迟是 3-10 微秒的数量级,即这是线程在其一直等待的互斥锁被释放后唤醒所需的时间。如果您正在最大限度地减少延迟,并且 setRegisterBits 的执行时间不到唤醒延迟的一半,并且不会阻塞,则可能需要使用 pthread_spinlock_t,但同样需要进行基准测试。

更好的选择可能是让一个工作线程调用setRegisterBits。该线程在线程安全队列上等待命令。许多线程可以将命令发布到该队列。您可能会考虑很多现成的线程安全队列,例如 tbb::concurrent_bounded_queueboost::lockfree::queue .这种模式的好处是它最大限度地减少了生产者线程的延迟。队列只会在发送和接收线程间消息时被阻塞,这可以以一种极其优化的方式完成。如果调用 setRegisterBits 比发送和接收线程间消息花费的时间更长,否则此方法可能会阻塞,则此方法是最佳选择。


对于基准锁定,有 Intel VTune Locks and Waits Analysis :

While Concurrency analysis helps identify where your application is not parallel, Locks and Waits analysis helps identify the cause of ineffective processor utilization. One of the most common problems is threads waiting too long on synchronization objects (locks). Performance suffers when waits occur while cores are under-utilized.

关于c++ - mmap 和 mutex 的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25794647/

相关文章:

C++ 奇怪的 "undefined reference"

java - long 和 double 赋值不是原子的——这有什么关系?

javascript - 如何中断nodejs中超时长时间运行的方法?

c++ - 运算符重载 <<

c++ - g++ : expected primary-expression before ‘[’ token

c++ - g++ libc.so 绝对路径交叉编译错误

linux - 使用 STLINK 和 Linux 刷新 ST 板

Linux bash - 打印用户输入

linux - 如何在没有中间文件夹的情况下将文件添加到 zip 存档

java - 使用共享对象实例化多个 Runnable 的含义是什么?