在内核中,可能出现多个进程(通过系统调用进入内核模式)访问同一个对象、进程和硬中断访问同一个对象、进程和软中断访问同一个对象、多个处理器访问同一个对象等现象,我们需要使用互斥技术,确保在给定的时刻只有一个主体可以进入临界区访问对象。
如果临界区的执行时间比较长或者可能睡眠,可以使用下面这些互斥技术。
(1)信号量,大多数情况下我们使用互斥信号量。
(2)读写信号量。
(3)互斥锁。
(4)实时互斥锁。
申请这些锁的时候,如果锁被其他进程占有,进程将会睡眠等待,代价很高。
如果临界区的执行时间很短,并且不会睡眠,那么使用上面的锁不太合适,因为进程切换的代价很高,可以使用下面这些互斥技术。
(1)原子变量。
(2)自旋锁。
(3)读写自旋锁,它是对自旋锁的改进,允许多个读者同时进入临界区。
(4)顺序锁,它是对读写自旋锁的改进,读者不会阻塞写者。
申请这些锁的时候,如果锁被其他进程占有,进程自旋等待(也称为忙等待)。
进程还可以使用下面的互斥技术。
(1)禁止内核抢占,防止被当前处理器上的其他进程抢占,实现和当前处理器上的其他进程互斥。
(2)禁止软中断,防止被当前处理器上的软中断抢占,实现和当前处理器上的软中断互斥。
(3)禁止硬中断,防止被当前处理器上的硬中断抢占,实现和当前处理器上的硬中断互斥。
在多处理器系统中,为了提高程序的性能,需要尽量减少处理器之间的互斥,使处理器可以最大限度地并行执行。从互斥信号量到读写信号量的改进,从自旋锁到读写自旋锁的改进,允许读者并行访问临界区,提高了并行性能,但是我们还可以进一步提高并行性能,使用下面这些避免使用锁的互斥技术。
(1)每处理器变量。
(2)每处理器计数器。
(3)内存屏障。
(4)读-复制更新(Read-Copy Update,RCU)。
(5)可睡眠RCU。
使用锁保护临界区,如果使用不当,可能出现死锁问题。内核里面的锁非常多。定位很难,为了方便定位死锁问题,内核提供了死锁检测工具lockdep。