首页 > 代码库 > 5,内核同步

5,内核同步

  • 内核抢占 
    1. 无论在抢占还是非抢占内核中,运行在内核态的进程都可以自动放弃CPU.称为计划性进程切换.但是,抢占式内核在相应引起进程切换的异步事件的方式上有差异,称为强制性进程切换.
    2. 抢占式内核的特点: 一个在内核态运行的进程,可能在执行内核函数期间被另一个进程取代.可抢占式的目的是减少用户态进程的分派延迟(即从进程变为可执行状态到它实际开始运行之间的间隔).但是它会引起不容忽视的开销.
    3. 只有当内核正在执行异常处理程序,且内核抢占没有被显示禁止时,才可能抢占内核.同时本地CPU必须打开本地中断.
    4. 需要同步的情况: 当计算的结果依赖于两个或以上的交叉内核控制路径的嵌套方式时,可能出现竞争条件.临界区是一段代码,在其他的内核控制路径能够进入临界区前,进入临界区的内核控制路径必须全部执行完这段代码. 必须确保在任意时刻只有一个内核控制路径处于临界区.
    5. 不需要同步的:1)中断处理程序和tasklet不必编写成可重入函数; 2)仅被软中断和tasklet访问的每CPU变量不需要同步; 3)仅被一种tasklet访问的数据结构不需要同步.
  • 每CPU变量:最好的同步技术是吧设计不需要同步的内核放在首位.因为显式的同步原语都有性能开销. 吧内核变量声明为每CPU 变量. 
    1. 仅当确定在系统的CPU上的数据在逻辑上是独立的时候才使用.
    2. 主要是数据结构的数组,每个CPU对应数组的一个元素.在主存中被排列以使每个数据结构存放在Cache的不同行.所以,并发访问不会引起Cache行的切用和失效
    3. 对来自不同CPU的并发访问提供保护,但是对来自异步函数的访问不提供保护.
    4. 原则:内核控制路径应该在禁用抢占的情况下访问每CPU变量.
  • 原子操作: 
    1. 若干汇编指令具有"读-修改-写"类型.即访问存储器单元两次,一次读,一次写.
    2. 确保这样的操作在芯片级是原子的.任何这样的操作都必须以单个指令执行.
  • 优化和内存屏障 
    1. 使用优化的编译器时,指令不会严格按照他们在源代码中出现的顺序执行.此外,CPU通常并行地执行若干条指令,且可能重新安排内存访问.
    2. 但是在处理同步时,必须避免指令重新排序.所以,所有的同步原语起优化和内存屏障的作用.
    3. 优化屏障:保证编译程序不会混淆放在原语操作之前和之后的汇编指令.但并不保证不使当前CPU把汇编指令混在一起执行.
    4. 内存屏障:在原语执行之前,原语之前的操作已经完成,类似于防火墙.
  • 自旋锁 
    1. 加锁技术:当内核控制路径必须访问共享数据结构或进入临界区时,就需要为自己获取一把"锁".
    2. 自旋锁用在多CPU下.如果锁开着,就获取锁并继续自己的执行.相反,当锁由运行在另一CPU上的内核控制"锁着"时,就在周围"旋转"反复执行一条紧凑的循环指令(忙等).直到锁被释放.
    3. 在自旋锁忙等时,内核抢占还是有效的.等待自旋锁释放的进程有可能被更高优先级的进程替代.
  • 读写自旋锁 
    1. 为了增加内核的并发能力.在没有写的情况下,允许并发的读操作.