smp_load_acquire
、smp_store_mb
和 smp_store_release
是 Linux 内核中用于多核数据同步的关键内存屏障原语。它们通过控制指令和内存访问顺序,确保多核系统中的数据可见性和操作原子性。
smp_load_acquire
作用:提供「获取(acquire)语义」,确保该操作之后的所有内存访问不会被重排序到它之前。
典型场景:读取共享状态(如锁、信号量标志位)时,保证读到最新值并建立后续操作的顺序约束。
int flag = smp_load_acquire(&shared_flag);
if (flag == 1) {
// 后续操作看到的是生产者设置的完整状态
}
- 与
smp_store_release
配对使用时,可形成生产者-消费者模型[1][6]。 - 替代显式读屏障(如
smp_rmb
),减少代码量并提高可读性[2][8]。
smp_store_release
作用:提供「释放(release)语义」,确保该操作之前的所有内存访问不会被重排序到它之后。
典型场景:写入共享变量(如锁释放、状态更新)时,保证写入前的操作对其他核可见。
// 生产者更新共享状态
smp_store_release(&shared_flag, 1);
- 与
smp_load_acquire
配合,实现跨核同步(如UNLOCK
后其他核LOCK
可见更新)[6][9]。 - 避免完整内存屏障的开销,仅约束前后操作顺序[7][8]。
smp_store_mb
作用:写入变量后插入完整内存屏障(smp_mb
),保证该操作前的所有内存访问对其他核可见。
典型场景:需要严格顺序的任务状态更新(如进程调度标志修改)[4]。
smp_store_mb(task->state, TASK_RUNNING);
- 实现为写屏障(
smp_wmb
)加变量写入的组合[3][4]。 - 比
smp_store_release
更严格,适用于无明确配对操作的场景(如单边状态变更)[4][7]。
对比与选择
函数 | 屏障类型 | 典型用途 | 性能开销 |
---|---|---|---|
smp_load_acquire | 单向(获取) | 读取共享状态 | 低 |
smp_store_release | 单向(释放) | 写入共享状态(配对 acquire) | 低 |
smp_store_mb | 双向(完整屏障) | 强制全局可见性 | 较高 |
设计建议:
- 优先使用
smp_load_acquire/smp_store_release
对,减少不必要的屏障开销[2][8]。 - 仅在需要全局顺序性(如 MMIO 或复杂状态机)时使用
smp_store_mb
[4][7]。
这三种原语是 Linux 内核实现无锁数据结构、RCU 和同步机制的基础,通过精细控制内存顺序,兼顾了多核性能与数据一致性[1][6][9]。
Citations:
[1] https://blog.csdn.net/sz66cm/article/details/142914148
[2] https://sbexr.rabexc.org/latest/sources/35/f2dc3df03913d1.html
[3] https://blog.csdn.net/weixin_52622200/article/details/135707455
[4] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0124r8.html
[5] https://simonsungm.cool/2023/07/11/Memory-Ordering/
[6] https://blog.csdn.net/u012849539/article/details/106883197
[7] https://www.cnblogs.com/ellabrain/p/15836843.html
[8] https://github.com/aparri/memory-model/blob/master/Documentation/recipes.txt
[9] http://wangzhou.github.io/Linux%E5%86%85%E6%A0%B8memory-barrier%E6%96%87%E6%A1%A3%E5%AD%A6%E4%B9%A0/
[10] https://tinylab.org/memory-ordering-part2/
[11] https://www.cnblogs.com/fanguang/p/16643434.html
[12] https://stackoverflow.com/questions/61749435/pairing-acquire-release-operations-between-user-and-kernel-space
[13] https://github.com/cncounter/translation/blob/master/tiemao_2020/46_Linux_Kernel_Memory_Barriers/README.md
[14] https://www.linuxjournal.com/article/8212
[15] https://quant67.com/post/linux/memory-barriers/memory-barriers.html
[16] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0124r5.html
[17] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4322.html