1、为什么spinlock临界区不允许发生抢占?
答:如果spinlock临界区允许抢占,那么如果在临界区发生中断时,中断返回时会去检查抢占调度,这里有两个问题,一是抢占调度相当于持有锁的进程睡眠,违背了spinlock锁不能睡眠和快速执行的设计语义;二是抢占调度进程可能会去申请相同的spinlock锁,那么会导致发生死锁。 在进入spinlock加锁的入口,会首先调用preempt_disable()函数来禁止抢占。
2、linux内核中经典spinlock实现有什么缺点?
答:经典spinlock实现中,spinlock如果获取不到锁,会一直自旋等待,也就是忙等待,这样就会比较浪费CPU。特别是经典实现中不会调用wfe之类的之类进行睡眠,从而导致忙等待时会一直消耗CPU功耗。而最新内核实现中(以ARM为例),spinlock在忙等待时,会调用wfe指令使CPU睡眠,在锁被其他进程释放时,会调用SEV之类唤醒睡眠等待的CPU重新抢占spinlock锁,从而达到降低功耗的作用。
3、为什么spinlock的临界区不能睡眠?
答:spinlock的临界区只允许被中断抢占(如果是spin_lock_irq甚至中断也不能够抢占),任何其他进程不能抢占,直到该进程完成了spinlock的临界区。如果进程在spinlock的临界区睡眠(就会发生睡眠调度,主动调用schedule()、schedule_timeout()让出CPU),那么其他进程就可能获取到CPU,并且其他进程也有可能申请相同的spinlock锁,又由于spinlock自旋等待不会睡眠,从而导致死锁,因此spinlock临界区不允许睡眠。