有人可以解释的使用WRITE_ONCE和READ_ONCE?
并且在内部WRITE_ONCE使用易失性限定符。为什么?
如何WRITE_ONCE和READ_ONCE解决高速缓存一致性的问题?
*(volatile __u8_alias_t *)p和(volatile __u8_alias_t *)* p之间的区别是什么?
它们本身并没有做任何事情来解决并发性,但它们确实阻止编译器做一些愚蠢的事情,例如从同一内存位置加载一个值两次。例如,如果您正在访问硬件并且不想触发多个总线访问,这可能会影响将来的读写,这一点很重要。
编译器会做这种事情,因为通常它们被允许优化对别名变量的访问,因为它们认为它们知道整个系统的行为方式。
为了真正支持并发,您需要了解内存一致性以及在另一个值可见时可以保证哪些值对一个线程可见。这包括将操作声明为原子操作(通过读取较小部分的值并组合结果来避免“撕裂” )和指定内存屏障。内存屏障允许您确保受另一个字段保护的值在访问时对另一个线程可见。
volatile单独读取或写入类似于 C 的_Atomicload 或 store with memory_order_relaxed,并且通常编译为相同的 asm。请参阅何时在多线程中使用 易失性?(从来没有,除了在 Linux 内核中)了解为什么这是真的的一些底层细节。
在像 ARMv8 这样具有加载获取和存储释放指令的 ISA 上,您更愿意使用这些指令(通过smp_load_acquire/ smp_store_release)而不是volatile READ_ONCE单独的屏障。大多数较旧的 ISA 仅具有普通负载和单独的屏障指令。内核的READ_ONCE/WRITE_ONCE模型是围绕它设计的。