引言
在多核处理器系统中,并发访问共享资源是操作系统内核必须面对的核心挑战。Linux内核作为全球最广泛使用的操作系统内核,提供了一套完整且高效的同步机制。本文将从底层硬件原理出发,深入分析Linux内核中主要的同步原语及其实现机制。
一、并发问题的本质
1.1 竞态条件(Race Condition)
当多个执行流(进程、中断、软中断等)同时访问共享数据,且至少有一个执行流进行写操作时,就会产生竞态条件。内核中的竞态可能来源于:
- 对称多处理(SMP):多个CPU核心同时执行内核代码
- 抢占式调度:进程上下文被更高优先级任务抢占
- 中断嵌套:硬件中断打断正在执行的临界区
- 内核抢占:可抢占内核中,线程可能在任意位置被切换
1.2 内存屏障(Memory Barrier)
现代处理器采用乱序执行(Out-of-Order)和写缓冲优化,导致内存操作的可见性无法保证。Linux内核提供以下内存屏障原语:
barrier() // 编译器屏障,阻止编译器重排序
mb() // 全内存屏障,保证所有读写顺序
rmb() // 读内存屏障,保证读操作顺序
wmb() // 写内存屏障,保证写操作顺序
smp_mb() // SMP环境下的内存屏障
smp_rmb() // SMP环境下的读屏障
smp_wmb() // SMP环境下的写屏障
二、原子操作(Atomic Operations)
原子操作是最底层的同步原语,利用硬件提供的原子指令(如x86的LOCK前缀)保证操作的不可分割性。
typedef struct { int counter; } atomic_t;
// 原子读
#define atomic_read(v) READ_ONCE((v)->counter)
// 原子设置
#define atomic_set(v, i) WRITE_ONCE((v)->counter, (i))
// 原子加
static __always_inline void atomic_add(int i, atomic_t *v){
asm volatile(LOCK_PREFIX "addl %1,%0"
: " m" (v->counter)
: "ir" (i));
}
64位原子操作使用atomic64_t,底层依赖cmpxchg指令实现CAS(Compare-And-Swap)循环。
三、自旋锁(Spinlock)
3.1 核心原理
自旋锁是一种忙等待锁,当线程无法获取锁时,不会进入睡眠,而是在一个循环中不断检查锁的状态。这种方式避免了上下文切换的开销,但会消耗CPU周期。
// 自旋锁结构(简化)
typedef struct {
arch_spinlock_t raw_lock;
} spinlock_t;
// 获取自旋锁
static __always_inline void spin_lock(spinlock_t *lock){
raw_spin_lock(

发表评论 取消回复