Answers:
在Linux内核的上下文中,当人们谈论抢占时,他们通常指的是内核中断自身的能力-本质上是在运行内核代码时切换任务。允许发生这种情况非常复杂,这可能是导致内核抢占时间较长的主要原因。
起初,大多数内核代码无论如何都无法中断,因为它受到了大内核锁的保护。越来越多的内核代码逐渐消除了该锁定,从而允许并行并行调用多个内核(随着SMP系统变得越来越普遍,这一点变得越来越重要)。但这仍然不能使内核本身具有先发制人的优势。即把更多的发展是,在最终PREEMPT_RT
补丁集,其最终在主线内核合并(并且是能够先发制人的BKL反正)。如今,可以将内核配置为或多或少的可抢占式,这取决于所追求的吞吐量和延迟特性。有关详细信息,请参见相关的内核配置。
从内核配置的解释中可以看到,抢占会影响吞吐量和延迟,而不是并发。在单CPU系统上,抢占还是有用的,因为它允许以较短的响应时间处理事件。但是,这也会导致吞吐量降低(因为内核花费时间来切换任务)。抢占允许单个或多个CPU系统中的任何给定CPU更快地切换到另一个任务。多CPU系统上的限制因素不是抢占,而是大的或其他的锁定:任何时候代码被锁定,都意味着另一个CPU无法开始执行相同的操作。
抢占式内核仅意味着没有大内核锁。
从一开始,Linux就具有抢占式多任务处理(即用户代码是抢占式的)(据我所知,Linus上载到funet ftp服务器上的第一个Linux 0.0.1早已是抢先式多任务处理)。例如,如果执行了多个压缩或编译过程,则它们从第一刻起便并行执行。
与当时-广泛使用的Win31相反。在Win31上,如果任务是从“内核”获得CPU的,则默认情况下,它有责任确定何时将控制权交还给OS(或其他任务)。如果某个进程对此功能没有特殊支持(需要额外的编程工作),则在执行该功能时,所有其他任务都将被挂起。甚至集成到Win31中的大多数基本应用程序都可以正常工作。
抢占式多任务处理意味着任务无法根据需要分配CPU。相反,如果它们的时隙到期,则内核会将CPU移开。因此,在抢占式操作系统中,编写错误或运行不正常的进程不能冻结OS,也不能避免其他进程运行。Linux总是抢占用户空间进程。
Big Kernel Lock表示在某些情况下,在内核空间内,仍然可能会有一些锁,从而阻止其他进程运行受保护的代码。例如,您不能同时挂载多个文件系统-如果您提供了多个挂载命令,它们仍将连续执行,因为挂载需要分配大内核锁。
要使内核具有抢占性,就必须消除此大内核锁定,即使挂载和任何其他任务能够同时运行。这是一项艰巨的工作。
从历史上看,这通过增加对SMP(多CPU支持)的支持变得非常紧迫。第一次有真正的多CPU主板。后来将多个CPU(“核心”)集成到一个芯片中,今天真正的多CPU主板已经很少了(它们通常在昂贵的服务器系统中)。真正真正的单核系统(只有一个cpu,只有一个核)也很少见。
因此,您的问题的答案不是“什么是非抢占性的原因”,因为它始终是抢占性的。真正的问题是,是什么使抢先式内核执行真正必要。答案是这样的:多CPU多核系统的比例在增加。
这不是技术问题的答案,而是针对 OP提出的特定问题的历史答案:“较早的Linux内核无法抢占的原因是什么?”
(我假设,正如@peterh在他的回答和评论中所解释的,OP通过“非抢占性”指的是以下事实中的一个或两个,即一个用户进程可能位于内核中(在API中)。时间和/或大内核锁定。)
莱纳斯·托瓦尔兹(Linus Torvalds)对学习操作系统的工作方式很感兴趣,而他学习的方法就是编写一个。他的模型,基础和初始开发环境是Minix,这是一种用于教育目的的现有OS(即非生产OS),它不是免费的(如当时的开源)-它不像啤酒那样免费,要么)。
因此,他写了一个没有抢先的内核(在其他答案中提到了Big Kernel Lock),因为如果您出于教育目的想要快速启动并运行新操作系统,那就是这样做的方法:这要简单得多。支持用户程序和设备的并发多重编程的内核已经足够困难-使内核本身并发是非常困难的。
如果他知道那么流行/有用/重要的Linux将会如何发展……他可能会以同样的方式做到这一点。(仅IMO,我不知道他的实际想法。)因为您必须走路才能跑步。
而且这种方式已经存在了很长一段时间,因为a)要使Linux变成今天(甚至是当时的样子)还有很多其他工作要做,并且b)进行更改将是一项艰巨的任务。 (如其他答案中所述)。