自旋锁
自旋锁是为多核系统设计,在SMP系统上可以实现真正的自旋锁,但对于UP系统,自旋锁仅仅做了抢占和中断,没有实现真正的“自旋”。如果在单核中配置了CONFIG_DEBUG_SPINLOCK,按照smp系统来编译。
自旋锁的目的:
针对于多核系统,保护一小段短小的临界区操作,保证这段临界区的操作是原子的,从而避免并发的竞争冒险,在linux内核中的自旋锁用于那些包含内核数据结构的操作。可以看到许多内核数据结构中都嵌入有spinlock,这些大部分是用于保证它自身操作的原子性。上锁-操作-解锁。
自旋锁的等待执行的过程是,反复执行一条紧凑的循环检测指令,直到锁被释放。自旋锁是循环检测忙等,自旋锁所保护的临界区必须小,且操作过程必须短。
自旋锁常出现的并发“干扰”
1、 中断。软硬中断,仅在代码可能访问临界区时需要。中断到来会导致中断服务程序的执行,如果中断服务程序要访问临界区,势必会将原子性打破,故而中断服务程序中要访问临界区必须加spinlock保护。
2、 内核抢占。仅存在于支持可抢占式的内核中
单核多核中,有一个进程访问临界区时,倘若内核是支持抢占式内核,就会有可能发生另一个进程发起抢占现象,出现了并发访问临界区现象,在这种内核形式下,要求我们在访问临界区加锁同时要禁止内核的抢占功能,解锁后在使能内核抢占。
3、 smp系统,其他处理器对临界区访问
这种系统中,多处理器同时工作,可能导致物理上的多进程并发,这就需要在内存加个表示,每一个进入临界区的代码都必须检查这个标志,看是否有进程已经进入这个临界区,这种情况下检查标准的代码必须是原子的和快速的,这就要求必须精心化实现,
6个API和对应功能:
宏 功能
spin_lock(lock) 指定的自旋锁
spin_lock_irq(lock) 禁止本地中断并获取指定的自旋锁
spin_lock_irqsave(lock,flags) 保存本地中断信息,禁止本地中断,并获取指定的锁
spin_unlock(lock) 释放指定的锁
spin_unlock_irq(lock) 释放指定的锁,并激活本地中断
spin_unlock_irqrestore(lock,flags) 释放指定的锁,并恢复本地中断到之前的状态
spin_lock_init(lock) 动态初始化指定的锁
spin_trylock(lock) 试图获取指定的锁,如果未获取,则返回非0