内核为不同请求服务
- 内核抢占
- 如果进程正在执行内核函数时,允许发生内核切换,则这个内核就是可抢占内核
- 可抢占内核的特点: 一个在内核态运行的进程,可能在执行内核函数期间被另外一个进程取代
同步原语
- Linux内核使用的同步技术
每CPU变量
- 系统为每个CPU分配数据,一个CPU不能访问其他CPU的元素
- 仅针对来自不同CPU的并发访问提供保护,对来自异步函数的访问不提供保护
原子操作
- 避免“读-修改-写”指令引起的竞争条件
- Linux中的原子操作
内存屏障
- 优化屏障: 保证编译程序不会混淆放在原语操作之前的汇编语言指令和放在原语操作之后的汇编语言指令
- 内存屏障: 确保在原语之后的操作开始执行之前,原语之前的操作已经完成
- Linux使用6个内存屏障原语
自旋锁
- 忙等
- spin_lock宏:请求自旋锁,详细步骤见P204
- 读写自旋锁:允许并发读
顺序锁
- 类似读写自旋锁,为写者赋予较高的优先级
读-拷贝-更新(RCU)
- 允许多个读者和写者并发
- 只保护动态分配并通过指针引用的数据结构
- 在被RCU保护的临界区,任何内核控制路径都不能睡眠
- 写者更新数据结构时,更新数据结构的副本,修改完毕后,写者改变指向数据结构的指针,使其指向被修改的副本。由于修改指针操作是原子操作,所以,不会导致数据不一致。
信号量
- 两种信号量
- 内核信号量
- System V IPC信号量
- 信号量的获取和释放(P212)
- 读写信号量
- 两种信号量
禁止本地中断
进制和激活可延迟函数
- 修改thread_info中的软中断计数器
对内核数据结构的同步访问
- 保护异常锁访问的数据结构
- 信号量
- 保护中断所访问的数据结构
- 针对多个中断处理程序访问一个数据结构
- 禁止本地中断
- 保护可延迟函数所访问的数据结构
- 自旋锁
- 保护由异常和中断访问的数据结构
- 本地中断进制+自旋锁
- 保护由异常和可延迟函数访问的数据结构
- 本地中断禁止+自旋锁
- 保护由中断和可延迟函数访问的数据结构
- 本地中断禁止+自旋锁
- 保护由异常、中断和可延迟函数访问的数据结构
- 本地中断进制+自旋锁
避免竞争条件的实例
- 引用计数器
- 大内核锁
- 内存描述符读写信号量
- slab高速缓存链表的信号量
- 索引节点的信号量