在Linux开发的早期,开发者就面临这样的问题,即不同类型的上下文(用户进程对中断)如何访问共享的数据,以及如何访问来自多个CPU同一上下文的不同实例。
在Linux内核中,临界区的代码或者是由进程上下文来执行,或者是由中断上下文来执行。在单CPU上,可以用cli/sti指令来保护临界区的使用,例如:
unsigned long flags;
save_flags(flags);
cli();
/* critical code */
restore_flags(flags);
但是,在SMP上,这种方法明显是没有用的,因为同一段代码序列可能由另一个进程同时执行,而cli()仅仅能单独地为每个CPU上的中断上下文提供对竟争资源的保护,它无法对运行在不同CPU上的上下文提供对竟争资源的访问。因此,必须用到自旋锁。
所谓自旋锁,就是当一个进程发现锁被另一个进程锁着时,它就不停地“旋转”,不断执行一个指令的循环直到锁打开。自旋锁只对SMP有用,对单CPU没有意义。
有三种类型的自旋锁:基本的、读写以及大读者自旋锁。读写自旋锁适用于“多个读者少数写者”的场合,例如,有多个读者仅有一个写者,或者没有读者只有一个写者。大读者自旋锁是读写自旋锁的一种,但更照顾读者。大读者自旋锁现在主要用在Sparc64和网络系统中。