在问题之前进行一些讨论。 Linux 2.4内核不是preemtive,所以如果我们在内核模式下执行系统调用时需要上下文切换,我们只需要set_need_resched来提升标志然后当我们回到用户模式时,我们检查标记并执行上下文切换。
让我们将它与具有抢占式内核的linux 2.6进行比较。 我们不能只取2.4的内核并将set_need_resched(raise flag)更改为schedule()(重新安排的指令执行),所以在linux内核2.6中有一个计数器preempt_count,它每次都会在spin_lock()上增加并减少spin_unlock()保护。
实际上,此字段“preempt_count”确定是否可以抢占内核。例如,从时钟中断返回时,如果条件:
(current->need_resched == 1) && (current->preempt_count == 0)
为真,然后内核执行context-switch。
问题是为什么linux 2.6的内核在保持类型为spinlock的锁时会阻止抢占。
如果内核没有阻止抢占,可能会发生什么情况?你能尽可能详细地给我一个具体的例子吗?
谢谢。
答案 0 :(得分:0)
您是否读过有关可互换锁(如互斥锁或信号量)的内容?
在他们的情况下,如果不能进行锁定,则线程可以使自己进入睡眠状态,例如优先考虑锁定所有者(如果睡觉)可以更快地完成工作。特别是,可能希望获取锁的线程在cpu上运行,锁所有者被安排继续。
另一方面,对于自旋锁,假设没有人睡觉 - 这意味着特别是忙等待(即停留在cpu上)不会阻止锁拥有者。如果锁定,则所有者正在某处运行。但是,让我们说它进入了睡眠状态。这意味着等待线程将浪费时间旋转,因为所有者无法恢复工作。只有在调度程序确定它之后它才会被抢占,但是服务员和所有者之间没有建立任何关系。所以特别是服务员可能会回到cpu继续忙着等待,而锁主人仍然没有机会跑。
所以至少这将是一个巨大的性能问题。在实践中,它只会导致高负载的活锁,而内核无法向前推进。