引言

在多核处理器系统中,并发访问共享资源是操作系统内核必须面对的核心挑战。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(                        
                    
点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部