旧 Linux 内核不可抢占的原因是什么?

Nar*_*den 16 linux scheduling kernel

为什么最初的 Linux 开发人员选择实现非抢占式内核?是为了保存同步吗?

据我所知,Linux 是在 90 年代初开发的,当时个人电脑只有一个处理器。非抢占式内核在此类 PC 中有何优势?然而,为什么优势被多核处理器削弱了呢?

Ste*_*itt 27

在 Linux 内核的上下文中,当人们谈论抢占时,他们通常指的是内核中断自身的能力——本质上是在运行内核代码的同时切换任务。允许这种情况发生非常复杂,这可能是内核需要很长时间才能被抢占的主要原因。

起初大多数内核代码无论如何都不能被中断,因为它受到大内核锁的保护。该锁逐渐从越来越多的内核代码中消除,允许对内核进行多个同时调用(随着 SMP 系统变得越来越普遍,这变得更加重要)。但这仍然没有使内核本身成为可抢占的。这还需要更多的开发,最终形成PREEMPT_RT补丁集,该补丁集最终合并到主线内核中(并且无论如何都能够抢占 BKL)。如今,内核可以配置为或多或少可抢占,这取决于您所追求的吞吐量和延迟特性;详见相关内核配置

从内核配置中的解释可以看出,抢占影响吞吐量和延迟,而不是并发。在单 CPU 系统上,抢占仍然有用,因为它允许以更短的反应时间处理事件;然而,它也会导致较低的吞吐量(因为内核会花时间切换任务)。抢占允许单个或多个 CPU 系统中的任何给定 CPU 更快地切换到另一个任务。多 CPU 系统的限制因素不是抢占,而是锁,无论是大的还是其他的:任何代码获取锁的时间,都意味着另一个 CPU 无法开始执行相同的操作。


pet*_*erh 12

抢占内核仅意味着没有Big Kernel Lock

Linux 从一开始就有抢占式多任务处理(即用户代码是可抢占的)(据我所知,由 Linus 上传到 funet ftp 服务器的第一个 Linux 0.0.1 已经是抢占式多任务处理)。例如,如果您执行了多个压缩或编译过程,它们会从一开始就并行执行。

与当时广泛使用的 Win31 相反。在 Win31 上,如果任务从“内核”获得 CPU,默认情况下它负责确定何时将控制权交还给操作系统(或其他任务)。如果一个进程对这个特性没有特别的支持(这需要额外的编程工作),那么在执行它时,所有其他任务都被挂起。即使是集成到 Win31 中的大多数基本应用程序也是如此。

抢占式多任务意味着任务无法按照自己的意愿分配 CPU。相反,如果它们的时隙到期,内核就会从它们那里获取 CPU。因此,在抢占式操作系统中,编写不当或运行不良的进程无法冻结操作系统,或避免其他进程运行。Linux 总是抢占用户空间进程。

大内核锁意味着在某些情况下,在内核空间内,仍然可能有一些锁,阻止其他进程运行受保护的代码。例如,你不能同时挂载多个文件系统——如果你给出了多个挂载命令,它们仍然是连续执行的,因为挂载东西需要分配大内核锁。

使内核抢占需要消除这个大内核锁,即使挂载和任何其他任务能够并发运行。这是一项艰巨的任务。

从历史上看,由于对 SMP(多 CPU 支持)的支持越来越多,这变得非常紧迫。第一次,真的有多CPU主板。后来多个 CPU(“核心”)被集成到单个芯片中,今天真正的多 CPU 主板已经很少见(它们通常在昂贵的服务器系统中)。此外,真正的单核系统(只有一个 CPU,单核)也很少见。

因此,您的问题的答案不是“非抢占性的原因是什么”,因为它始终是先发制人的。真正的问题是,是什么让抢占式内核执行真正必要。答案是:多CPU、多核系统的比例不断增加。