Linux内核中的原子操作:无锁编程的基础

张开发
2026/4/5 20:56:56 15 分钟阅读

分享文章

Linux内核中的原子操作:无锁编程的基础
Linux内核中的原子操作无锁编程的基础作为一名深耕操作系统和嵌入式开发的工程师我对Linux内核中的原子操作机制有着深入的理解。原子操作是实现无锁并发编程的基础它保证了操作的不可分割性。原子操作的基本概念原子操作是指不可被中断的操作要么全部执行完成要么完全不执行不可分割操作过程中不会被其他CPU或中断打断内存序保证原子操作通常包含内存屏障高性能比锁机制更轻量级原子操作的类型1. 整数原子操作// 定义原子变量 atomic_t counter ATOMIC_INIT(0); // 读操作 int val atomic_read(counter); // 写操作 atomic_set(counter, 100); // 增加/减少 atomic_inc(counter); atomic_dec(counter); // 增加指定值 atomic_add(10, counter); atomic_sub(5, counter); // 先增加后读取 int new_val atomic_inc_return(counter); // 比较并交换 int old_val atomic_cmpxchg(counter, expected, new_val);2. 位操作// 设置位 set_bit(0, bitmap); // 清除位 clear_bit(1, bitmap); // 翻转位 change_bit(2, bitmap); // 测试并设置位 int old_val test_and_set_bit(3, bitmap); // 测试位 if (test_bit(4, bitmap)) // 位已设置3. 64位原子操作// 64位原子变量 atomic64_t big_counter ATOMIC64_INIT(0); // 64位操作 atomic64_set(big_counter, 10000000000LL); long long val atomic64_read(big_counter); atomic64_inc(big_counter);原子操作的实现x86架构实现// x86使用lock前缀实现原子操作 static inline void atomic_inc(atomic_t *v) { asm volatile(lock incl %0 : m (v-counter)); } // 比较并交换使用cmpxchg指令 static inline int atomic_cmpxchg(atomic_t *v, int old, int new) { return cmpxchg(v-counter, old, new); }ARM架构实现// ARM使用LDREX/STREX指令对 static inline void atomic_inc(atomic_t *v) { int tmp, result; asm volatile( atomic_inc\n 1: ldrex %0, [%2]\n add %0, %0, #1\n strex %1, %0, [%2]\n teq %1, #0\n bne 1b : r (result), r (tmp) : r (v-counter) : cc); }使用场景1. 引用计数struct object { atomic_t refcount; // ... }; struct object *object_get(struct object *obj) { atomic_inc(obj-refcount); return obj; } void object_put(struct object *obj) { if (atomic_dec_and_test(obj-refcount)) { // 引用计数为0释放对象 kfree(obj); } }2. 统计计数器atomic_t packet_count ATOMIC_INIT(0); void receive_packet(void) { // 无锁增加计数器 atomic_inc(packet_count); } int get_packet_count(void) { return atomic_read(packet_count); }3. 标志位操作unsigned long flags; // 设置初始化完成标志 set_bit(FLAG_INITIALIZED, flags); // 检查标志 if (test_bit(FLAG_INITIALIZED, flags)) // 已初始化 // 原子地设置并检查 if (!test_and_set_bit(FLAG_BUSY, flags)) // 成功获取资源原子操作与锁的对比特性原子操作自旋锁互斥锁开销极低中等较高可睡眠否否是适用场景简单计数临界区保护复杂操作可扩展性极好好一般注意事项1. ABA问题// ABA问题示例 // 线程1读取值为A // 线程2改为B又改回A // 线程1的CAS成功但值已被修改过 // 解决方案使用带版本号的原子操作 atomic64_t ptr_and_version;2. 复合操作// 错误两个原子操作之间不是原子的 if (atomic_read(counter) 0) { atomic_dec(counter); // 可能被其他线程修改 } // 正确使用循环CAS int old_val, new_val; do { old_val atomic_read(counter); if (old_val 0) return; new_val old_val - 1; } while (atomic_cmpxchg(counter, old_val, new_val) ! old_val);性能优化建议优先使用原子操作对于简单的计数和标志位使用原子操作代替锁避免过度竞争高竞争下原子操作会退化为循环考虑使用锁使用本地缓存对于频繁更新的计数器先更新本地缓存再批量提交合理选择数据类型32位原子操作比64位更高效总结原子操作是Linux内核中实现无锁并发的基础机制它提供了极高的性能和良好的可扩展性。作为嵌入式开发者合理使用原子操作可以显著提升多核系统的并发性能。

更多文章