graph TB
A["多核 CPU"] --> B["共享内存"]
B --> C["竞态条件\nrace condition"]
C --> D["数据损坏"]
C --> E["逻辑错误"]
C --> F["崩溃"]
A -.->|同步原语| G["内核同步"]
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#E8D5F5,stroke:#CE93D8,color:#333
style C fill:#FFB3C6,stroke:#F48FB1,color:#333
style D fill:#F48FB1,stroke:#FFB3C6,color:#333
style E fill:#F48FB1,stroke:#FFB3C6,color:#333
style F fill:#F48FB1,stroke:#FFB3C6,color:#333
style G fill:#B5EAD7,stroke:#80CBC4,color:#333
graph LR
A["read-modify-write"] --> B{"需要原子性?"}
B -->|"是"| C["CPU 指令\nxadd / lock cmpxchg"]
B -->|"否"| D["非原子\n可能出错"]
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#FFF9C4,stroke:#F9A825,color:#333
style C fill:#B5EAD7,stroke:#80CBC4,color:#333
style D fill:#FFB3C6,stroke:#F48FB1,color:#333
x86 原子指令:
LOCK 前缀
XADD:原子交换 + 加
CMPXCHG:原子比较交换
1.3 关键启示
原子操作 = CPU 指令保证
轻量——无锁
适合计数器、标志位
二、自旋锁(Spin Lock)
2.1 原理
graph TB
A["CPU 0"] -->|"加锁\n失败"| B["忙等 (spin)"]
B --> C{"锁可获得?"}
C -->|"否"| B
C -->|"是"| D["获得锁"]
D --> E["临界区"]
E --> F["解锁"]
F --> G["CPU 1 获得"]
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#FFB3C6,stroke:#F48FB1,color:#333
style C fill:#FFF9C4,stroke:#F9A825,color:#333
style D fill:#B5EAD7,stroke:#80CBC4,color:#333
style E fill:#B5EAD7,stroke:#80CBC4,color:#333
style F fill:#B5EAD7,stroke:#80CBC4,color:#333
style G fill:#C7CEEA,stroke:#9FA8DA,color:#333
graph TB
A["进程 A"] -->|"down()"| B{"信号量 > 0?"}
B -->|"是"| C["减 1,获得"]
B -->|"否"| D["睡眠"]
D --> E["等待唤醒"]
E --> B
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#FFF9C4,stroke:#F9A825,color:#333
style C fill:#B5EAD7,stroke:#80CBC4,color:#333
style D fill:#FFDAB9,stroke:#FFAB76,color:#333
style E fill:#FFDAB9,stroke:#FFAB76,color:#333
graph TB
A["读者"] -->|无锁| B["读取旧版本"]
C["写者"] -->|"分配新版本"| D["更新指针"]
D --> E["等待旧读者完成"]
E --> F["释放旧版本"]
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#B5EAD7,stroke:#80CBC4,color:#333
style C fill:#C7CEEA,stroke:#9FA8DA,color:#333
style D fill:#FFDAB9,stroke:#FFAB76,color:#333
style E fill:#FFB3C6,stroke:#F48FB1,color:#333
style F fill:#B5EAD7,stroke:#80CBC4,color:#333
4.2 RCU API
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include<linux/rcupdate.h>
// 读侧 rcu_read_lock(); p = rcu_dereference(global_ptr); // 读 p rcu_read_unlock();
graph TB
A["读者 A"] -->|"读锁"| B["可获得"]
C["读者 B"] -->|"读锁"| B
D["写者"] -->|"写锁"| E{"读者有锁?"}
E -->|"是"| F["等待"]
E -->|"否"| G["独占"]
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#B5EAD7,stroke:#80CBC4,color:#333
style C fill:#C7CEEA,stroke:#9FA8DA,color:#333
style D fill:#FFB3C6,stroke:#F48FB1,color:#333
style E fill:#FFF9C4,stroke:#F9A825,color:#333
style F fill:#FFDAB9,stroke:#FFAB76,color:#333
style G fill:#E8D5F5,stroke:#CE93D8,color:#333
// 访问 int *p = this_cpu_ptr(&my_counter); *p = 100;
优势:无锁(每个 CPU 独立)
6.3 完成量(Completion)
1 2 3 4 5 6 7 8 9
#include<linux/completion.h>
DECLARE_COMPLETION(my_comp);
// 等待者 wait_for_completion(&my_comp);
// 完成者 complete(&my_comp);
适用:进程间同步
6.4 内存屏障
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include<linux/compiler.h>
// 通用屏障 barrier();
// 读屏障(防止读重排) rmb();
// 写屏障 wmb();
// 全屏障 mb();
// SMP 屏障 smp_mb(); smp_rmb(); smp_wmb();
七、死锁
7.1 死锁的 4 个条件
graph TB
A["死锁 4 条件"] --> B["互斥\n(Mutual Exclusion)"]
A --> C["持有并等待\n(Hold & Wait)"]
A --> D["不可剥夺\n(No Preemption)"]
A --> E["循环等待\n(Circular Wait)"]
style A fill:#FFB3C6,stroke:#F48FB1,color:#333
style B fill:#FFF9C4,stroke:#F9A825,color:#333
style C fill:#FFF9C4,stroke:#F9A825,color:#333
style D fill:#FFF9C4,stroke:#F9A825,color:#333
style E fill:#FFF9C4,stroke:#F9A825,color:#333
graph TB
A["时间源"] --> B["硬件时钟\nRTC"]
A --> C["HPET\n高精度定时器"]
A --> D["TSC\n时间戳计数器"]
A --> E["jiffies\n内核滴答"]
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#FFDAB9,stroke:#FFAB76,color:#333
style C fill:#E8D5F5,stroke:#CE93D8,color:#333
style D fill:#FFB3C6,stroke:#F48FB1,color:#333
style E fill:#B5EAD7,stroke:#80CBC4,color:#333
graph TB
A["硬件时钟"] -->|"中断"| B["tick_periodic"]
B --> C["更新 jiffies"]
C --> D["调用调度器"]
D --> E["处理定时器"]
E --> F["更新时间统计"]
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#E8D5F5,stroke:#CE93D8,color:#333
style C fill:#FFDAB9,stroke:#FFAB76,color:#333
style D fill:#FFB3C6,stroke:#F48FB1,color:#333
style E fill:#B5EAD7,stroke:#80CBC4,color:#333
style F fill:#B5EAD7,stroke:#80CBC4,color:#333
graph TB
A["内核同步 + 定时器"] --> B["原子操作\nCPU 指令"]
A --> C["自旋锁\n短期锁"]
A --> D["信号量/Mutex\n长期锁"]
A --> E["RCU\n读者无锁"]
A --> F["jiffies + 定时器\n时间管理"]
style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
style B fill:#E8D5F5,stroke:#CE93D8,color:#333
style C fill:#FFDAB9,stroke:#FFAB76,color:#333
style D fill:#FFB3C6,stroke:#F48FB1,color:#333
style E fill:#B5EAD7,stroke:#80CBC4,color:#333
style F fill:#FFF9C4,stroke:#F9A825,color:#333