linux 自旋锁
自旋锁非常简单,一个自旋锁就是一个互斥设备,它只有两个值:“锁定”与“解锁”,如果锁可用,则“锁定”位被设置,而代码继续进入临界区,相反,如果锁被其他人获得,则代码进入忙循环并重复检查这个锁,直到该锁可用为止,这个就是“自旋”的部份。
自旋锁最初是为了在多处理器系统上使用而设计的,只要考虑到并发问题,单处理器工作站在运行可抢占内核时其行为就类似于SMP,如果非抢占式的单处理系统进入某个锁上的自旋状态,则会永远自旋下去,也就是说,没有任何其他线程能够获得CPU来释放这个锁,因此出于对此原因的考虑,非抢占式的单处理器系统上的自旋锁被优化为不做任何事情,但改变IRQ掩码状态的例程是个例程外。
在使用自旋锁时需要使用的函数:
spinlock_t my_lock=SPIN_LOCK_UNLOCKED
或者: void spin_lock_init(spinlock_t *lock);
进入临界区必须: void spin_lock(spincock_t *lock)
所有的自旋锁等待在本质上是不可中断的,一旦调用了spin_lock,在获得锁之前将一直处于自旋状态,
使用自旋锁的规则:
1.任何拥有自旋锁的代码都必须是原子的,它不能休眠,事实上它不能因为任何原因放弃处理器,除了服务中中断以外,(某些情况下此时也不能放弃处理器)
2.任何时候,只要内核代码拥有自旋锁,在相关处理器上的抢占就会被禁止,甚至在单处理器系统上,也必须以同样的方式禁止抢占以避免竞态。
3.在驱动程序中获得自旋锁,而在锁中又发生中断,在中断处理例程中又有锁,这亲在中断例程自旋时,非中断代码将没有任何机会来释放这个锁,处理将永远自旋下去,因此,我们需要在拥有自旋锁时禁止中断。
4.自旋锁必须在可能短时间内拥有,拥有自旋锁的时间越长,其他处理器不得不自旋锁以等待释放该自旋锁的时间就越长,而它不得不永远自旋的可能性就越大,长时间拥有锁将一些优先级高的进程得不到执行。
终上述可以得出锁必须:不能休眠、中断、锁中锁、抢占,时间应越短越好。
自旋锁函数:
void spin_lock (spinlock_t *lock)
void spin_lock_irqsave(spinlock_t *lock,unsigned long flags)
void spin_lock_irq(spinlock_t *lock)
void spin_lock_bh(spinlock_t *lock)
自旋锁可以运行在(硬件或软件)中断上下文中,则必须使用其中禁止中断的spin_lock形式使用其他锁迟早会导致系统死锁。