两个月新增80万行代码,Linux内核为什么不会崩?

  8月初,当Linux5.8RC版本开放测试时,大多数的新闻都聚焦于它的大小,称其为“史上最大的内核版本”。正如LinusTorvalds本人指出的那样,“尽管没有任何一件事情能脱颖而出……但5.8似乎是我们有史以来最大的发行版之一。”

  确实,刚刚发布的Linux内核5.8RC具有超过14,000个commit,约80万行新代码以及大约100名新贡献者。要知道,距离5.7正式版发布才仅仅过去了约2个月的时间。Linux内核维护者StevenRostedt认为,5.8之所以变得如此之大,很有可能是因为COVID-19疫情让很多人难以出门旅行,所有人都因此能够在这期间完成比平时更多的工作。

  Rostedt表示,从一个经验丰富的Linux内核贡献者和维护者的角度来看,5.8RC发行版特别令人震惊的并不是它的大小,而是它的空前规模对于那些正在维护它的人来说却没有造成困扰,“我认为这是因为Linux具有比世界上任何软件项目都好的工作流程。”

  拥有最佳的工作流程意味着什么?对Rostedt而言,这归结为Linux内核开发人员随着时间的推移建立的一系列基本规则,以使他们能够持续不断地大规模、可靠地发展Linux内核项目。Rostedt站在一个Linux内核资深维护者的角度,为我们分享了庞大的Linux内核项目30年来是如何有条不紊地运转的。

  第一个关键因素是Git

  首先让我们从Linux项目的历史来看。在该项目的早期(1991-2002年),人们只能直接将补丁发送给LinusTorvalds。准确地说,Linus从项目的子维护者那里获取补丁,而这些子维护者从其他代码贡献者那里获取补丁。随着Linux内核变得越来越大,代码越来越复杂,很快他们就发现,一切都变得很难扩展和跟踪,并且项目将始终面临合并不兼容代码的风险。

  这导致Linus开始探索包括BitKeeper在内的各种版本管理工具。BitKeeper是一种最早的分布式版本管理的方法,其他的版本管理系统通常使用签出/修改/签入协议,而BitKeeper则向所有人提供整个仓库的副本,并允许开发人员将其变更发送出去以进行合并。Linux在2002年开始短暂地采用了BitKeeper,但是由于其本身是一个专有软件,被认为不符合社区对开源工作的信念,于是该工具在2005年停止使用。为了寻找替代品,Linus消失了一段时间,并带着git回来了,后者成为了更强大的分布式版本管理系统,并且是管理流程的第一个重要实例化。Git的出现使Linux开发在今天依然运转良好。

  Rostedt为我们列出了Linux内核工作流程中,围绕Git展开的七个重要基本原则。

  七大基本原则

  每次commit只能做一件事

  Linux的中心原则是,所有更改都必须分解为小步骤进行——您的每个commit都只能做一件事。这并不意味着每个commit都必须很小,比如对在数千个文件中使用的函数的API进行简单更改,可以使更改量很大,但仍然可以接受,因为它是针对某一项单一任务的更改。通过始终遵循此原则,项目维护者可以更轻松地识别和隔离任何有问题的更改,而不影响其他的功能。

  commit不能破坏构建

  不仅应该将所有更改分解为尽可能小的变量,而且还不能破坏内核。即每个步骤都必须完全起作用,并且不引起退化。这就是为什么对函数原型的更改还必须更新调用它的每个文件,以防止构建中断的原因。因此,每个步骤都必须作为一个独立的更改来工作,这将我们带到了下一点:

  所有代码都是二等分的

  如果在某个时候发现了错误,则需要知道是哪个更改导致了问题。从本质上讲,二等分是一种操作,它使开发者可以找到所有发生错误的确切时间点。

  为此,请转到最后一个已知的工作commit所在的节点,并且已知第一个commit已损坏,然后在该点测试代码。如果可行,则前进到下一个节点;如果不是,则返回更上层的节点。这样一来,开发者就可以在十几次编译/测试中,从成千上万的可能commit中分离出导致问题出现的commit。Git甚至可以通过gitbisect功能帮助自动化该过程。

  重要的是,这只有在开发者遵守以前的规则的情况下才能很好地起作用:每个commit仅做一件事。否则,您将不知道是commit的许多更改中的哪一个导致了问题;如果commit破坏了构建让整个项目无法正常启动,同时等分线又恰好落在了该commit上,则您将不知道接下来是该往上一个节点测试还是往下一个节点测试,因为它们都有问题。这意味着您永远都不应编写依赖于将来commit的commit,例如:调用尚不存在的函数,或更改全局函数的参数而不更改同一commit中的所有调用者。

  永远不要rebase公共分支

  Linux项目工作流程不允许rebase他人使用的任何公共分支。因为rebase这些公共分支后,已重新基准化的commit将不再与基于原存储库中的相同commit匹配。在树的层次结构中,不是叶子的公共主干部分不能重新设置基准,否则将会破坏层次结构中的下游分支。

  Git正确合并

  其他的版本管理系统是合并来自不同分支代码的噩梦,它们通常难以弄清代码冲突,并且需要大量的手动工作来解决。而Git的结构可以轻松完成这项工作,因此Linux项目也从中直接受益。这就是为什么5.8版本的大小并不重要的重要原因。在5.8-RC1发布周期中,平均每天有200个commit,并从5.7版本中继承了880个合并。一些维护者注意到了其中增加的工作量,但是对此仍然没有感到什么太大的压力或者导致倦怠。

  保留定义明确的commit日志

  不幸的是,这可能是许多其他项目忽略的最重要的原则之一。每个commit都必须是独立的,这也应该包括与该commit相应的日志。内核贡献者必须在更改的commit日志中做出说明,让所有人了解与正在进行的更改相关的所有内容。Rostedt提到,他自己的一些最冗长和最具描述性的变更日志,往往是针对一些单行代码提交的,因为这些单行代码更改是非常细微的错误修复,且代码本身包含的信息极少。因此更改的代码越少,日志反而应该说明得更详细。

  在一个commit过了几年之后,几乎没有人会记得当初为什么进行更改。Git的blame功能就可以显示这些代码的修改记录。比如一些commit可能非常古老,也许您需要去除一个锁定,或者对某些代码进行更改,而又不确切知道它为什么存在,就可以使用gitblame来查看。编写良好的代码更改日志可以帮助确定是否可以删除该代码或如何对其进行修改。Rostedt说:“有好几次我很高兴能在代码上看到详细的变更日志,因为我不得不删除这些代码,而变更日志的描述让我知道我这么做是可以的。”

  持续测试和集成

  最后一项基本原则是开发过程中进行持续测试和持续集成。在向上游发送commit请求之前,开发者会测试每个commit。Linux社区还有一个名为Linux-next的镜像,它提取维护人员在其存储库的特定分支上进行的所有更改,并对其进行测试以确保它们能正确集成。Linux-next非常有效地运行着整个内核的可测试分支,该分支将用于下一个发行版。Linux-next是一个公共仓库,任何人都可以测试它,这种情况经常发生——人们现在甚至发布有关Linux-next中代码的错误报告。事实上,已经进入Linux-next几周的代码基本上可以确定会最终进入主线发行版中。

  软件开发行业的黄金标准

  所有的这些原则制度使Linux社区能够以如此庞大的规模(常规9周为一个版本迭代周期)发布令人难以置信的可靠代码(每个版本平均10,000次commit,最后一个版本超过14,000次commit)。

  Rostedt指出,Linux项目取得空前成功的另一个因素是他们社区的文化。Linux内核社区内部存在一种持续改进的文化,这使他们能够首先采用这些实践。同时他们还有一种信任的文化,“我们有一条清晰的途径,人们可以通过该途径做出贡献,并随着时间的推移证明他们愿意且有能力推进该项目的发展。这将建立一个相互信任的关系网,这些关系对于项目的长期成功至关重要。”

  Rostedt认为,内核开发者的肩上承担着比其他任何项目都要重的责任。“在内核层,我们别无选择,只能遵循这些做法。因为所有其他应用程序都在内核之上运行,内核中的任何性能问题或错误都将导致上层的应用程序出现性能问题或错误。我们必须完美处理内核中的错误,否则,整个计算机系统都将受到损害。我们非常关心每个错误,因为内核中的错误带来的风险很高,这种思维方式也能让我们很好地服务于任何软件项目。”

  上层的应用程序会因为错误而崩溃,造成的后果可能是惹恼用户,但风险不高。而内核的错误可能导致的后果是让计算机上的一切都出现问题,承担着巨大的风险。

  这就是Linux内核开发工作流程被视为软件开发行业黄金标准的原因。

  下载YPS行业门户系统APP,分享赚金币换豪礼

  相关文章

  关键词:Linux

  免费玩转,LinuxLab全面支持龙芯开发环境zstd有望进入Linux5.9,下一步可能是支持压缩系统固件FedoraIoT确认将在Fedora33中升级为“OfficialEdition”KaliLinux2020.3正式发布爆料:迅雷正在适配Linux平台FBI、NSA发联合安全警告:俄罗斯黑客使用新型Linux恶意软件进行攻击