我是Linux的新手,正在阅读Rubini&科比特。我对与spinlocks
有关的一个陈述感到困惑;这本书说明了
如果非抢先式单处理器系统进入了 旋转锁定,它将永远旋转;没有其他线程能够获得 CPU释放锁定。因此,在单处理器系统上进行自旋锁操作 没有抢占功能被优化为什么也不做,除了 那些改变IRQ掩蔽状态的那些。
此外,书中还说明了
内核抢占案例由自旋锁代码本身处理。任何时候内核 代码保存一个自旋锁,在相关处理器上禁用抢占。甚至是单处理器 系统必须以这种方式禁用抢占,以避免竞争条件。
问题:在单处理器系统上,如果内核代码(代表用户进程执行)持有自旋锁,则禁用内核抢占,那么另一个进程怎么可能有机会运行并因此尝试获取自旋锁?为什么Linux内核在内核代码持有自旋锁时会禁用内核抢占?
答案 0 :(得分:7)
你的第一个问题的答案是第二个问题背后的推理。
内核获取的自旋锁可以通过关闭抢占来实现,因为这可以确保内核在没有其他进程干扰的情况下完成其关键部分。重点是在内核释放锁之前,另一个进程将无法运行。
没有理由必须以这种方式实施;它只是一种实现它的简单方法,可以防止任何进程在内核持有的锁上旋转。但是这个技巧只适用于内核获得锁定的情况:用户进程无法关闭抢占,如果内核正在旋转(即它试图获取自旋锁,但另一个进程已经拥有它),最好先放弃抢占上!否则系统将挂起,因为内核正在等待一个不会被释放的锁,因为持有它的进程无法释放它。
内核获取自旋锁是一种特殊情况。如果用户级程序获取螺旋锁,则不会禁用抢占。
答案 1 :(得分:1)
进程A和进程B都访问相同的数据,因此您定义了SPIN LOCK。如果A持有锁但保持启用抢占。那么A可能会被安排出去,而B有机会跑步。如果B尝试获取锁。 B将旋转并浪费cpu。
自旋锁旨在提高效率并保护小而快速的关键区域。所以旋转块禁用抢占。如果您想锁定但保持启用先占功能。您可以使用互斥锁。
当进程A释放锁定时,再次启用抢占。因此其他进程有机会运行。在此之前,只能运行硬件中断和软件irq。
答案 2 :(得分:0)
自旋锁仅在单处理器上禁用抢占。 因此,在使用单个处理器的情况下:假设调度器的队列中包含以下进程: P1,P2,P3,P4-全部请求自旋锁L。 他们所有人都将在排队时获得锁(即P1后跟P2等)
在单处理器系统上禁用抢占的原因是: 如果不: P1保持锁定,并且在预定时间后。 现在,P2开始执行,并且假设请求相同的自旋锁。由于P1尚未释放自旋锁,因此P2必须旋转而不执行任何操作。因此浪费了P2的执行时间。让P1释放锁定然后让它被抢占更有意义。 另外,由于没有其他处理器,因此,通过禁止抢占,我们知道永远不会有另一个进程在另一个处理器上并行运行并访问相同的关键部分。
类似地,如果关键部分与中断部分共享,我们需要在该处理器上本地禁用中断。在中断的情况下,它们永远不会被调度。因此,重要的是,中断永远不要请求被其中断的进程已经持有的锁。这样的进程将永远不会在其他任何处理器上运行,因为它没有被调度,因此它将永远不会有机会释放锁。因此,中断处理程序将永远不会完成导致死锁。因此,在这种情况下,我们总是在处理器上禁用本地中断。