38 并发之外的同步机制
# 38 并发之外的同步机制
大多数关于同步的解释始于线程并终于锁,但仅线程安全并不能反映内核的设计承受能力。并发只是内核必须防范的多个维度之一。内核中同步的目的不是保护代码不被多个线程执行,而是维护不相互等待的执行上下文之间共享状态的完整性。
在内核空间中,同一个函数可能同时在多个CPU上执行。重要的不是代码是否被重入,而是它触及的数据是否受到保护。临界区由数据而非代码定义。同步确保共享内存结构(任务列表、文件描述符、套接字缓冲区)即使在被可抢占线程、中断处理程序或延迟下半部分访问时也能保持一致。被序列化的不是调用路径,而是数据的边界。
系统安全不仅依赖于线程间的原子性,还包括对抢占的控制、中断的排除、核心间的可见性、对象生命周期的执行以及访问的限制。竞争、崩溃或安全漏洞可能并非源于并行执行本身,而是源于不安全的访问——通过中断更新、过早释放或对共享状态的未检查修改。
内核提供自旋锁、互斥锁和顺序锁用于互斥,使用RCU在延迟回收时实现无锁读取,在必须维护局部性的区域禁用抢占和CPU迁移,应用per-CPU变量完全消除竞争。为确保内存安全,它将引用计数与kref等生命周期感知对象结合,并使用RCU确保读取者从不在内存被释放后观察到它。在可见性必须跟随初始化的无锁路径中,它使用内存屏障强制执行顺序。这些机制不是避免竞争的通用解决方案,而是在特定上下文中消除特定形式不安全的目标工具。
内核不将同步视为优化,而是视为基础。任何可从多个上下文访问的数据必须考虑每一种可能的交互——SMP并发、中断抢占、软中断干扰、NMI进入和异步拆卸。它必须在抢占下安全,在CPU迁移中正确,通过每个引用有效,在释放后不可用。它必须在使用前准备好,并在整个可见期受到保护。
确保内核安全的不是它并行运行,而是它保持对共享内容的控制。内核中的同步是对该控制的执行,它保护数据而非函数,维护状态而非流程,确保共享结构即使通过多个执行路径到达也能保持一致。