Linux内核

Linux内核（Linux kernel）是一种开源的类Unix操作系统宏内核。整个Linux操作系统家族基于该内核部署在传统计算机平台（如个人计算机和服务器，以Linux发行版的形式）和各种嵌入式平台，如路由器、无线接入点、专用小交换机、机顶盒、FTA接收器、智能电视、数字视频录像机、网络附加存储（NAS）等。工作于平板电脑、智能手机及智能手表的Android操作系统同样通过Linux内核提供的服务完成自身功能。尽管于桌面电脑的占用率较低，基于Linux的操作系统统治了几乎从移动设备到主机的其他全部领域。截至2017年11月，世界前500台最强的超级计算机全部使用Linux。

Linux内核最早是于1991年由芬兰黑客林纳斯·托瓦兹为自己的个人电脑开发的，他当时在Usenet新闻组`comp.os.minix`登载帖子，这份著名的帖子标志着Linux内核计划的正式开始。如今，该计划已经拓展到支持大量的计算机体系架构，远超其他操作系统和内核。它迅速吸引了一批开发者和用户，利用它作为其他自由软件项目的核心，如著名的 GNU 操作系统。而今天，Linux 内核已接受了超过1200家公司的近12000名程序员的贡献，其中包括一些知名的软硬件发行商。

从技术上说，Linux 只是一个符合POSIX 标准的内核。它提供了一套应用程序接口（API），通过接口用户程序能与内核及硬件交互。仅仅一个内核并不是一套完整的操作系统。有一套基于 Linux 内核的完整操作系统叫作Linux 操作系统，或是GNU/Linux（在该系统中包含了很多GNU 计划的系统组件）。

Linux 内核是在GNU通用公共许可证第2版之下发布的（加上一些非自由固件、blob与各种非自由许可证），是一个开源项目协作的突出例子。它的版本支持根据版本最长可达6年，贡献者遍布世界各地，日常开发相关的讨论在Linux 内核邮件列表上。

## 历史

<image>

1991年，林纳斯·托瓦兹，一名21岁的就读于芬兰赫尔辛基大学的计算机科学专业学生，基于一些简单的想法，打算编写一个操作系统内核。他通过英特尔80386汇编语言的任务切换器和一个终端驱动程序开始工作。8月25号，他在`comp.os.minix`新闻组里发了一封帖子：

之后，许多人为这个项目贡献了代码。在早期，MINIX社区向 Linux 内核贡献了代码和想法。当时，GNU 项目已经创建了许多自由操作系统所需的组件，但是它自己的内核 GNU Hurd 尚不完整且无法使用；而BSD操作系统还没有摆脱合法的阻碍。因此，尽管早期版本的 Linux 功能有限，但它迅速获得了开发人员和用户。

到1991年9月，Linux内核版本 0.01 在芬兰大学和研究网络（FUNET）的FTP服务器（ftp.funet.fi）上发布。它有10,239行代码。在1991年10月，0.02版本的内核发布了。

1991年12月，0.11版本的内核发布。由于它可以由运行相同内核版本的计算机编译，因此该版本是第一个自托管的 Linux 内核。当托瓦兹于1992年2月发布0.12版本时，他采用了 GNU 通用公共许可证（GPL），而不是以前的自行起草的许可证，原先的许可证不允许商业再分发。

1992年1月19日，第一篇文章提交给新的新闻组`alt.os.linux`出现。1992年3月31日，该新闻组更名为 `comp.os.linux`。

X Window 系统随后被移植到Linux上，所以在1992年3月，Linux 0.95 是第一个能够运行X的版本。从0.1x到0.9x的版本号大幅跨越是因为期望没有大的缺失部分的版本1.0的即将出现。然而，这被证明是错误的。从1993年到1994年初，出现了0.99版本的15个开发版本。

1994年3月14日，Linux内核1.0.0发布，共176,250行代码。随后的1995年3月，有310,950行代码的 Linux 内核1.2.0发布。

在1996年6月9日发布的 Linux内核2.0版本之后，以2.0为大版本的主要更新有如下这些：

- 1999年1月25日 - 发布Linux内核2.2.0（1,800,847行代码）
- 1999年12月18日 - 针对2.2.13的 IBM 大型机补丁发布，允许 Linux 内核用于企业级机器
- 2001年1月4日 - 发布 Linux 内核2.4.0（3,377,902行代码）
- 2003年12月17日 - 发布 Linux 内核2.6.0（5,929,913行代码）

从2004年开始，发布过程发生了变化，新的内核每隔2-3个月定期发布，编号为2.6.0、2.6.1，直到2.6.39。

2011年7月21日，Torvalds宣布发布Linux内核3.0：“2.6. 的日子过去了”。与Linux 2.6.39相比，大的技术变化同版本跃升没有关系；它标志着内核的20周年纪念。基于时间的发布过程保持不变。

2013年6月发布的Linux内核版本3.10包含15,803,499行代码，而2015年6月发布的4.1版本已发展到超过1950万行代码，由近14000名程序员贡献。

### 塔能鲍姆-林纳斯辩论

Linux不是微内核架构的事实曾经引起了林纳斯·托瓦兹与安德鲁·斯图尔特·塔能鲍姆之间一场著名的争论。1992年在Usenet讨论群组 comp.os.minix开始了一场网络论战，讨论的主题在于操作系统架构的选择。稍后一些著名的骇客也加入讨论，如大卫·米勒、曹子德。这场辩论影响了Linux核心的设计走向。塔能鲍姆认为Linux内核采用的宏内核已经过时了，应该采取比较先进的微内核架构，引起了林纳斯的反击。

在2006年5月9日，这个主题被重新审视，并且在2006年5月12日塔能鲍姆写了一份立场声明。

## 架构

<image>

Linux是一个单体内核，支持真正的抢占式多任务处理（于用户态，和版本2.6系列之后的内核态）、虚拟内存、共享库、请求分页、共享写时复制可执行体（通过内核同页合并）、内存管理、Internet协议族和线程等功能。

设备驱动程序和内核扩展运行于内核空间（在很多CPU架构中是ring 0），可以完全访问硬件，但也有运行于用户空间的一些例外，例如基于FUSE/CUSE的文件系统，和部分UIO。多数人与Linux一起使用的图形系统不运行在内核中。与标准单体内核不同，Linux的设备驱动程序可以轻易的配置为内核模块，并在系统运行期间可直接装载或卸载。也不同于标准单体内核，设备驱动程序可以在特定条件下被抢占；增加这个特征用于正确处理硬件中断并更好的支持对称多处理。出于自愿选择，Linux内核没有二进制内核接口。

硬件也被整合入文件层级中。用户应用到设备驱动的接口是在/dev或/sys目录下的入口文件。进程信息也通过/proc目录映射到文件系统。

### 编程语言

Linux是用C语言中的GCC版（这种C语言有对标准C进行扩展）写的，还有几个用组合语言（用的是GCC的"AT&T风格"）写的目标架构短段。因为要支持扩展的C语言，GCC在很长的时间里是唯一一个能正确编译Linux的编译器。有许多其他的语言用在一些方面上，主要集中在内核构建过程中（这里指从源代码创建可启动镜像）。包括Perl、Python和多种脚本语言。有一些驱动可能是用C++、Fortran或其他语言写的，但是这样是强烈不建议的。

### 编译器兼容性

GCC是Linux内核源代码的缺省编译器。在2004年，Intel主张通过修改内核，以便Intel C++编译器能正确编译内核。在2009年，有通过修改内核2.6.22版而成功编译的报告（并带来平均8-9%效能增长）。

自从2010年，已经开始进行使用Clang建造Linux内核的努力，Clang是一个可作为替代的C语言编译器；截止2014年4月12日，官方内核几乎可以完全用Clang编译。致力于这个目标的计划叫做“LLVMLinux”，得名于Clang所基于的LLVM编译器下部构造。LLVMLinux不意图复制Linux内核或LLVM，因此它是由最终提交给上游计划的补丁构成的一个元计划。使Linux内核可以用Clang编译最大的好处是比GCC有更快的编译速度，内核开发者可以得益于由此而来的更快的工作流程。

### 接口

<image>

符合标准是Linux内核内部的普遍策略。另一个规则是Linux内核主线不接受只由专有用户空间软件使用的内核模块。

#### 内核至用户空间API

<image>

源代码可移植性确保符合标准的C程序可以在符合同样标准的任何系统上编译和运行。Linux内核开发、GNU C函数库和相关的实用工具致力于追随POSIX和单一UNIX规范。Linux内核API是内核的系统调用接口。

#### 内核至用户空间ABI

二进制可移植性将保证任何程序在符合标准的给定硬件平台上一旦编译通过，可以在符合同样标准的任何其他硬件平台上以编译后的形式运行。二进制可移植性是在基于Linux内核的操作系统上建造独立软件供应商（ISV）应用有商业可行性的本质要求。现有唯一的二进制兼容标准是Linux标准规范（LSB）。

#### 内核内API

<image>

在不同子系统间使用了数个内核内部API。其中一些是跨越多个发行版保持稳定的，另一些则不然。对于内核内API不作担保。维护者和贡献者可以在任何时候增加或变更它们。

内核内API的例子包括针对下列类别设备驱动程序的软件框架/API：

- Video4Linux – 用于视频捕捉硬件。
- 高级Linux声音体系（ALSA） – 用于声卡。
- New API – 用于网络接口控制器。
- 直接渲染管理器 – 用于图形加速器。
- KMS驱动器 – 用于视频显示控制器。
- mac80211 – 用于无线网络接口控制器。

#### 内核内ABI

Linux内核开发者选择不维护稳定的内核内ABI。

### 技术特性

#### 抢占式调度系统

<image>

Linux内核提供在特定条件下的抢先式调度。直到内核版本2.4，只有用户进程是抢先式的，就是说除了时间片用尽，在用户模式下执行的当前进程，如果有更高态优先级的进程进入`TASK_RUNNING`状态，它就会被中断。自从2.6系列Linux内核，增加了中断执行内核代码的任务的能力，但不是对于内核代码的所有段落。

Linux内核含有不同的调度器类。内核缺省使用的调度机制叫做完全公平调度器，它介入于内核版本2.6.23。这个缺省调度器类在内部也叫做`SCHED_OTHER`，而内核还含有两个遵循POSIX的实时调度类，分别叫做`SCHED_FIFO`（实时先进先出）和`SCHED_RR`（实时轮流式），二者都优先于缺省类。

通过使用实时Linux内核补丁`PREEMPT_RT`，可以支持对关键段落、中断处理器和“中断禁用”代码序列的完全抢先。实时Linux内核补丁部分地集成入主线内核已经带给它一些功能。抢先机制改善延迟、增进响应性，并使得Linux更加适合桌面和实时应用。老版本内核有所谓的巨锁，用于锁定粒度为整个内核的同步，它最终由Arnd Bergmann在2011年移除了。

还有叫做`SCHED_DEADLINE`的调度策略，实现了最近截止期限最先（EDF）算法，它增加于2014年3月30日发行的内核版本3.14。

#### 可移植性

<image>

尽管林纳斯·托瓦兹的初衷不是使Linux成为一个可移植的操作系统，今天的Linux却是全球被最广泛移植的操作系统内核。从移动电话到超级电脑，甚至于有人成功的将Linux内核在索尼出品的游戏机PS2及PS3和微软出品的游戏机Xbox上使用。Linux也是IBM超级计算机Blue Gene的操作系统。直至2011年11月，全球前五百大超级电脑（TOP500）有高达91.4%的比例采用Linux为它们的操作系统。一些为手机开发的操作系统，使用Linux内核的修改后的版本，其中包括谷歌Android、Firefox OS、HP WebOS和诺基亚Maemo。

#### 内核错误和oops

<image>

在Linux中，内核错误（Kernel panic）是指操作系统在监测到内核系统内部无法恢复的错误，相对于在用户空间代码类似的错误。操作系统试图读写无效或不允许的内存地址是导致内核错误的一个常见原因。内核错误也有可能在遇到硬件错误或操作系统BUG时发生。在许多情况中，操作系统可以在内存访问违例发生时继续运行。然而，系统处于不稳定状态时，操作系统通常会停止工作以避免造成破坏安全和数据损坏的风险，并提供错误的诊断信息。

在Linux上，oops即Linux内核的行为不正确，并产生了一份相关的错误日志。许多类型的oops会导致内核错误，即令系统立即停止工作，但部分oops也允许继续操作，作为与稳定性的妥协。这个概念只代表一个简单的错误。当内核检测到问题时，它会打印一个oops信息然后杀死全部相关进程。oops信息可以帮助Linux内核工程师调试，检测oops出现的条件，并修复导致oops的程序错误。

### 安全

计算机安全是一个非常公众化的主题，关系到Linux内核，因为大量在内核中的错误可能成为潜在的安全漏洞，是否允许提升权限漏洞或拒绝服务攻击源漏洞。在过去的几年中，许多这样的缺陷被发现，并在Linux内核中被修补好。新的安全功能被继续实现，以解决在Linux内核中的电脑不安全问题。

批评者指责内核开发人员，称他们掩盖（至少并未公布）安全漏洞。2008年，作为回应，Torvalds称：“个人认为，安全漏洞只是‘正常的漏洞’。这些漏洞我并不去掩盖，不过我不认为应当把它们特殊化，更不认为应该追踪并公示它们......我不理会整个安全团队，原因之一就是，我认为这些漏洞不仅美化还鼓励了错误的行为。这令安全人员成了‘英雄’，就犹如不修补正常漏洞的人就不值一提似的。而事实上，所有无聊的正常漏洞极为重要，仅仅因为它们实在太多了。我不认为该美化和关心那些严重的安全漏洞——它们并不及那些由死锁造成的随机严重崩溃来得更特殊。”

如2012年五月，SYSRET指令被发现在AMD和英特尔处理器间在实现方面有差异，这个差异在Windows、FreeBSD、XenServer和Solaris这些主流操作系统会导致漏洞。2012年六月，Linux核心中该问题已被修复。

2021年，来自明尼苏达大学的研究人员，曾借由贡献修补程式至Linux核心的名义，利用修补程式导入Bug和漏洞，以观察Linux核心社群的反应，再度故技重施时被发现，之后维护人员封锁了所有来自该大学的贡献，与移除过去该大学曾经贡献的程式码。

## 开发

### 开发者社区

截止2007年，内核开发已经从20位最活跃开发者写80%的代码转变为顶端30人写30%的代码，而顶端开发者花费更多的时间审核变更。开发者还可以按从属关系来归类；在2007年，顶端类属是“不知名”而顶端公司是Red Hat，它占有12%的贡献，而知名业余爱好者占3.9%。在2007年中所做内核变更已经由超过1900位开发者提交。一般假定Linux内核开发者社区由5000或6000名成员组成。

Linux基金会发表的 2016年Linux内核开发报告的更新表明，从版本3.18（2014年12月）至4.7（2016年7月）期间：平均每次发行有来自200-250个公司的大约1500位开发者作出贡献。顶端30位开发者贡献了稍大于16%的代码。在公司中，顶端贡献者是Intel（12.9%）和Red Hat（8.0%），第三和第四位为“none”（7.7%）和“unknown”（6.8%）类属。

### 开发过程与模式

一个想要对 Linux 内核进行修改的开发者一般就从对那个修改的开发和测试开始着手。接下来的过程取决于变化的重要程度，及修改该变更的子系统数量是由单个还是多个修补程序组成。如果仅仅是修改了由单个维护人员维护的单个子系统，那么这些修改的补丁代码就直接通过Cc中某个邮件列表发送给相关的维护人员。邮件列表的阅读者和子系统的维护人员将检查补丁代码并提供反馈。一旦审查过程完成，维护者接受他内核代码树中的补丁。如果这些更改被认为是够重要的错误修复，那么包含这些修补程序的拉取请求（pull request）将在几天内发送给Linus。否则，将在下一个合并窗口时向Linus发送拉取请求。合并窗口通常会持续两周，并在之前的内核版本发布后立即启动。

Linus Torvalds拥有对Linux内核能够接受哪些更改和谁可以成为维护者的最终决定权。内核维护者在他们自愿放弃之前将维持他们的角色。目前，没有任何已知的内核维护者被要求退出。此外，还没有一个内核维护者因与其他维护者的交互风格的因素而受到Linus批评的例子。这为维护者提供了宽松的社区空间。虽然内核开发社区的文化多年来有所改善，但曾有一段时间它的声誉很糟糕。认为自己遭受了不公正对待的开发者可以向Linux基金会的技术专家委员会报告。尽管如此，一些社区成员仍然不认同现在的讨论氛围。

#### 同 Linux 发行版的关系

大多数Linux用户运行一个由他们 Linux 发行版提供的内核。一些发行版搭载的是 Linux 的通用内核（也就是 “vanilla”或“stable”）版本。不过，一些Linux内核发行商（如Red Hat和SUSE）会维护他们自己的内核分支。这些发行商分支的内核版本通常相对于稳定版本（vanilla）而言更新的速度更慢一些，但是同样会包括所有相关的稳定版本分支的补丁。此外，他们同时也会增添一些新特性和对新硬件的支持，而这些支持是这些发行商分支基于的稳定分支所不包括的。

### 主线Linux

包含Linux内核的Linus Torvalds的Git树被称为主线Linux。每个稳定的内核发布都源自主线树，并经常在kernel.org上发布。主线Linux只对运行Linux的众多设备中的一小部分设备提供坚实的支持。非主线支持由独立项目（如Yocto或Linaro）提供，但在许多情况下需要设备供应商的内核。使用供应商内核可能需要一个板级支持包。

在主线Linux之外维护一个内核树已被证明是困难的。

主线化（Mainlining）是指将对设备的支持添加到主线内核中的努力，而以前只有在分支中支持或根本没有支持。这通常包括添加驱动程序或设备树文件。完成后，该功能或安全修复被视为mainlined。

### 重新开发的估价

<image>

按照传统商业软件开发的方式，重新开发Linux 2.6.0内核的估计代价将是6.12亿美元（4.67亿欧元、3.94亿英镑），以2004年的COCOMO人月估计模型.在2006年，欧盟资助的一项研究表明，重新开发Linux 2.6.8以后的内核，代价是8.82亿欧元（11.4亿美元、7.44亿英镑）。

截至2011年1月4日，使用当前的代码行（LOC）和大卫·惠勒的计算工资数，这将花费约30亿美元（约22亿欧元），才能够重新开发Linux的内核。

### 版本命名

Linux内核有三个不同的命名方案。早期版本：第一个版本的内核是0.01，其次是0.02,0.03,0.10,0.11,0.12（第一GPL版本),0.95,0.96,0.97,0.98,0.99及1.0。从0.95版有许多的补丁发布于主要版本版本之间。

旧计划（1.0和2.6版之间)，版本的格式为A.B.C，其中A,B,C代表：A大幅度转变的内核，这是很少发生变化，只有当发生重大变化的代码和核心发生才会发生，在历史上曾改变两次的内核：1994年的1.0及1996年的2.0； B是指一些重大修改的内核，内核使用了传统的奇数次要版本号码的软件号码系统（用偶数的次要版本号码来表示稳定版本）；C是指轻微修订的内核，这个数字当有安全补丁，bug修复，新的功能或驱动程序，内核便会有变化。自2.6.0（2003年12月）发布后，人们认识到，更短的发布周期将是有益的。自那时起，版本的格式为A.B.C.D，其中A,B,C,D代表：A和B是无关紧要的，C是内核的版本，D是安全补丁。

自3.0（2011年7月）发布后，版本的格式为3.A.B，其中A,B代表：A是内核的版本，B是安全补丁。而4.0（2015年4月）释出后，则延续3.A.B的命名格式，只是将主版号变更为4。

## 法律层面

### 许可证

原先托瓦兹将 Linux 置于一个禁止任何商业行为的条例之下，但0.12版本之后改用 GNU 通用公共许可证第二版。该协议允许任何人对软件进行修改或发行，包括商业行为，只要其遵守该协议，所有基于Linux的软件也必须以该协议的形式发表，并提供源代码。

托瓦兹曾经公开声称将Linux置于GNU通用公共许可证之下是他一生中所做的“最好的决定”。

#### GPL第三版

Linux 内核明确地仅发表在 GNU 通用公共许可证（GPL）第二版下，而不向被许可方提供选择“任何更高版本”的选项（这是常见的 GPL 扩展）。关于如何轻松地改变许可证以使用后来的 GPL 版本（包括第3版）以及这种更改是否合乎需要，存在着相当多的争论。托瓦兹本人在版本2.4.0的发布中明确指出，他自己的代码仅在版本2下发布。然而，GPL的条款规定，如果没有指定版本，那么可以使用任何版本；并且艾伦·考克斯指出，很少有其他 Linux 贡献者指定了特定版本的 GPL。

2006年9月，对29位关键内核程序员的调查显示其中的28位更倾向于使用 GPL 第二版（GPLv2）而非当时的 GPL 第三版（GPLv3）草案。托瓦兹评论说：“我认为一些外界人士......相信我才是那个古怪不合群的人，因为我这么大张旗鼓地不做 GPLv3 的忠实粉丝。”这些高水平的内核开发者就大众媒体对 GPLv3 的反对发表了评论，其中包括林纳斯·托瓦兹本人、葛雷格·克罗哈曼和安德鲁·莫顿。他们提到有关DRM/TiVo化、专利及“附加限制”的条款，并警告GPLv3对“开源宇宙”的巴尔干化。决定不采用 GPLv3 作为 Linux 内核许可证的托瓦兹在几年后重申了他的批评。

#### 固件争议

许可证争议的一个重点是Linux使用固件二进制包以支援某些硬件装置。理察·马修·斯托曼认为这些东西让Linux某部分成为非自由软件，甚至以此散布Linux更会破坏GPL，因为GPL需要完全可获取的源代码。

林纳斯·托瓦兹及Linux社群中的领导者，支持较宽松的许可证，不支持理察·马修·斯托曼的立场。社群中的Linux-libre提供完整的自由软件固件。

#### 载入式核心模组许可证

另一个争论点，就是载入式核心模组是否算是知识产权下的衍生创作，意即LKM是否也受GPL约束？托瓦兹本人相信LKM仅用一部分“公开”的核心界面，因此不算衍生创作，因此允许一些仅有二进制包裹的驱动程式或不以GPL宣告的驱动程式用于核心。但也不是每个人都如此同意，且托瓦兹也同意很多LKM的确是纯粹的衍生创作，也写下“基本上，核心模组是衍生创作”这样的句子。另一方面托瓦兹也说过：

特别像绘图卡驱动程式就有非常大的争议，也许到最后得由立法机关给个答案。

### SCO争议

在2003年3月，SCO Group对IBM提告，声称IBM将一些在SCO知识产权许可证保护下的Unix源代码植入Linux中，破坏了SCO给予IBM的源代码使用许可权。另外SCO也发出一大堆存证函给许多公司，警告他们在没有SCO许可权的情况下使用了Linux，此举可能导致侵犯知识产权，并且以起诉为手段对个别使用者施压。SCO也同时对Novell、戴姆勒克莱斯勒（DaimlerChrysler，在2004年7月被部分驳回）以及AutoZone提出告诉，且被Red Hat与其他反对SCO论点的公司反告。2007年8月24日，联邦法院审理SCO对Novell案（SCO v. Novell），法院认定Novell才是Unix商标的合法拥有者，而不是SCO。2010年3月20日，美国联邦第十巡回上诉法院宣判，Novell才是UNIX与UnixWare商标的合法拥有者。此项判决宣布后，已进入破产保护程序的SCO公司，决定停止继续提出诉讼。

## 基本资料

- 软件版本周期：Linux
- 域：Linux官方的吉祥物，一只叫Tux的企鹅
- 开发者：林纳斯·托瓦兹（Linus Torvalds）和几千名合作者
- 操作系统家族：类Unix系统
- 发行日期：0.02 (1991年10月5日)
- 编程语言：C语言、Rust、汇编语言
- 语言：多语言
- 内核类别：单核心
- 软件版本周期：7.1.7
- 软件版本周期：7.1.7
- 许可证：GPL（仅）第二版、各类封闭固件的许可证
- 域：Linux的吉祥物Tux