嵌入式100题(66):linux内核同步方式总结
linux内核同步方式总结
每CPU变量:
正如其名,每cpu变量即为每个CPU都有自己的变量,各个CPU仅访问自己的每CPU变量,可以想象每CPU变量一般的数据结构是一个数组。
type name[CPU_COUNT];
因此每CPU变量解决的是多CPU之间可能发生的竞争条件,而因内核抢占而产生了进程切换时,则很可能使每CPU变量产生竞争条件。
原子操作:
原子操作即在执行原子操作时,不可能被在执行的时候拆分成几条原子操作。
Linux内核通过一些手段来实现某些操作的原子性,例如:
操作码前缀为lock的汇编指令,即使多cpu下也能保证其后汇编指令的原子性,lock会锁定内存总线,保证在执行汇编指令时没有其他CPU同时读写内存。
多处理器中,Linux内核通过提供atomic_t类型封装了一系列原子操作,如atomic_inc(v)表示把1加到v。
优化和内存屏障:
简单的说,优化编译器会将原本的代码进行重排,已达到最优的处理方式,这样产生的问题是程序在执行的时候访问内存的顺序可能并不像我们程序中原本写的那样。当同步发生时(竞争条件),我们必须避免指令重排。
而优化屏障的意思就是在指令之间插入一道屏障,让这道屏障之前和之后的指令不可能因重排而跨越这道屏障,很形象吧。
自旋锁:
自旋锁是一种广泛的同步技术,它锁住的是一块临界区,进入临界区时需要先获取自旋锁,在离开临界区时需要释放自旋锁。如果已经有其他进程获取了该锁,那么当前想要获取该锁的进程只能在临界区门口来回溜达(自旋),直到获取该锁。自旋锁类似于现实生活中的给房间的门上锁,进入房间访问资源时需要锁住门,防止其他人同时进入房间,退出房间时,再打开锁。
顺序锁:
顺序锁和读写锁的区别就是顺序锁中,写锁可以在进程还未释放读锁的情况下获取写锁,这样写锁不会因为读锁而等待,但是读进程在读的时候必须考虑是否有写进程正在进行写操作。
信号量:
信号量和自旋锁类似,也是为了控制进程进入临界区,但是信号量和自旋锁的重大区别是:
自旋锁获取锁的过程,不会主动调用schedule()进行进程切换,而是占用cpu,拼命的自旋,类似于while耗时操作。
信号量中存在一个进程等待队列,未获取锁的进程将挂到该队列中,然后主动调用schedule()切换进程,让出cpu。
浙公网安备 33010602011771号