Linux内核测试现状揭秘

简介: 作者:邢万里 马涛

本文大部分内容由 https://lwn.net/Articles/734016/ 翻译改编而来。

内核测试的现状

新的内核总是会定期发布出来,但是其实大家并不是十分了解内核是如何被深入测试的。那么这里可以提前告诉大家,内核主干有可能并没有做过充分的测试,而稳定内核可能会更少。。。 So what is going on there? Is stable kernel really stable? 刚好今年9月在洛杉矶举办的《Linux Plumbers Conference》有一个BOF(birds of a feather)会议,Dhaval Ginal和Sasha Levin组织了一个关于内核测试的相关讨论,让我们一起去看看。

由于大部分BoF的参会人员来自各个主要的Linux发行商,所以Giani开场的时候提了一个问题:“大家对于稳定内核(stable kernels)都做过了多少测试呢?大家是不是都是仅仅测试自己发行的内核然后再从稳定内核中backport一些安全以及其他相关的修复呢?对于稳定内核的测试从来都是置之不理呢?“ 对于这个问题的答案么,他自己半开玩笑的建议:可以将测试留给了用户。除了上面这个半开玩笑的建议以外,大多数人都一致认为:目前对于稳定内核,除了简单的构建-启动测试以外,几乎很少有其他方面的测试。那么这个现象是如何造成的呢?

内核测试的困境

第一点:开发者很难知道该去选择什么样的上游内核(upstream kernel)来测试。linux-next tree和稳定内核以及内核主线(mainline)都是在不断地变化着,要想做到稳定测试是一件很难的事情。但是大家又都一致同意,能在代码发布出来之前,发现其中的BUG还是很有价值的,所以一些发行版的研发人员就尝试测试-rc1的内核。这样做的话,如果bug被发现,它们将在发布前就被修正,这样看起来是不错的,但是这样需要非常多的时间和机器去做好这件事。另外,测试时使用的哪个版本的内核配置,也会使这个问题的复杂度翻倍。

第二点:内核测试消耗大量的人力物力。有人举了一个生动的例子,红帽(RedHat)需要花费一年的时间去稳定RHEL选定的内核版本。而粗略估计有300个工程师去做这个事情,这也就是意味着一个公司需要花费了300个人年去测试和稳固一个内核(译者在此处还是要感谢一下REDHAT)。此外,在驱动程序中,通常驱动的自检程序是应该由内核开发人员编写,但将个人的测试变成可以更广泛使用的东西需要很多时间和精力,而驱动的作者根本没有时间去添加一个自检程序,所以驱动大多数是没有自检程序的。在许多情况下,正是由于这个原因,导致代码质量很差。因此,现有的大部分自检程序可能都是在子系统中并已经做了很好测试,这些测试用例还能发现的大部分的错误主要发生在与开发者自己运行的硬件架构不同有关,比如ARM相关的错误就是这样被发现的。

第三点:启动测试(boot testing)占了上游内核测试的大头,占据了开发者更多的精力,所以最新发布的内核肯定可以启动起来的。拥有特殊硬件的人会测试他们的驱动,所以通过这一测试也可以发现大部分驱动的bug。像Ftrace、调度器和内存管理由于使用的很广泛,所以他们的测试也比较充分。除了以上这些组件以外,内核中其他的一些非核心或者不是被普遍使用的功能就可能没有那么多的功能测试了。

第四点:内核测试门槛较高,如环境设备和知识储备。对于一些想要测试驱动程序的人来说,他可能没法获得相应的硬件,即使有硬件,他还需要深入了解设备是如何工作的。理想情况下,驱动程序的作者应该测试这些设备,而大部分情况下也确实是这样。不过这个解决方案仍然不是完美的。

第五点:测试覆盖不全面,测试方面单一。因为虽然驱动作者试图确保在他的测试用例下驱动程序是正确工作的,但是他们有着不同的动机,如果他被雇佣做这个事情那么可能测试会比较全面,而如果他仅仅是为了让他自己的硬件可以正常工作,那么可能测试不会太全面,同时相应的文档也基本没有。

第六点:需要制定测试指南和帮助文档。例如,在内核测试中我们还需要发现一些可能引入的性能退化(performance regressions),但是如果仅仅是做一些”随机性能测试“(random performance testing),这是很难发现性能退化的,因此我们需要制定一些性能测试指南,以便可以进行一些苹果对苹果(apples-to-apples,译为同类型的比较)的对比测试。再如,就像Mel Gorman的MMTests作为“kbench”这一性能测试套件的基础,貌似有些与会者对这个测试套件不熟悉,所以MMTests需要有更好的文档来帮助使用者去了解它。

第七点:进行内核测试的另一个困难是要内核配置的数量非常庞大。当稳定的内核被发布的时候,它可能有100个补丁,但任何测试套件都不可能执行许多次去测试这些补丁,那么测试稳定版本的意义到底是什么呢?

总结一下,在所有的这些测试工作中,最大问题就是资源,我们需要更多的人和更多的机器,从而可以更早地发现和修复错误。

企业是如何做的

我们再把话题切回到稳定内核。如果我们可以阻止所有可能的bug引入到内核,那么主线内核(mainline)无疑是完美的,我们也就不需要什么稳定分支了(stable trees)。当然现实是残酷的,完美也是不可能的,所以我们仍然需要稳定分支,但是发行版真的会使用稳定分支么?让我们一个一个看过去。

企业例子之一(红帽)

红帽有一个大型测试实验室,有6000多台各种各样的机器分布在世界各地。实验室使用Beaker并测试了大量不同的内核配置,目前内核测试主要集中在三个RHEL内核和两个Fedora内核上,未来他们会计划添加一些主线版本的内核。在红帽内部,不同的团队专注于他们感兴趣的驱动,比如存储团队在测试各种存储设备,而RDMA团队在测试RDMA类型的硬件。所以,对于红帽而言,他们只从稳定的树上去挑选(cherry-pick)一些修复的补丁。 RHEL的每个小版本内核都有8-10万个补丁,但是所有的这些补丁都来自上游而不是稳定分支。RHEL内核团队会查看稳定的分支和最新的主线内核,然后寻找有必要使用的补丁。至于对应的测试则取决于这些补丁是应用于哪一个子系统; 一些子系统在补丁追溯方面做得很好,而其他子系统则较差。对于稳定内核的使用,一般Red Hat只是编译了一下并用它来和RHEL内核做对比测试,以确定这些错误是来自上游还是在RHEL中引入的。

企业例子之二(SUSE和Ubuntu)

再看看SUSE,他们确实在构建稳定内核,但他们仅仅是为了挑选(cherry-pick)补丁。他们有考虑将稳定的内核测试添加到SUSE的测试网格(testing grid)中,但大家还不清楚它会对公司带来什么样的价值。Ubuntu面对的情况也是类似的:他们除了建立稳定的内核以外,并没有对它们进行正式的测试。

企业例子之三(Linaro)

Linaro目前正在为谷歌开发一个使用内核自检(kernel self-tests,缩写kselftest)和Linux测试项目(Linux Test Project,缩写LTP)来测试稳定的内核项目,这些测试会针对每个稳定的发布版本来进行。自检测试的确能发现bug,但编写这些自检测试的人可能并不是引入大多数错误的人。所以自检测试还只是一个开始,显然Linaro还需要增加更多的测试。

所以综合来看,版本发布者一般都只是关心,合并到稳定版本里的修复(fix)是否是正确的,但是他们只是从稳定版本中摘出修复(fix)然后放到自己的内核中做测试,对稳定内核本身的测试是非常有限的。于是有人建议可以由Linux基金会与Canonical,SUSE,Red Hat等公司一起组建一个合作项目,大家一起贡献一部分机器同时形成一套测试套件来进行稳定内核的测试。

测试的不断改善

例一:0天内核测试服务(0-Day kernel test service)。这个服务也不仅仅是构建和引导测试(build-and-boot tests),还包括一些性能测试。 kernelci.org项目也正在对许多不同的硬件进行构建和引导测试(build-and-boot tests),这些都是非常有价值的,但他们没有做任何真正的功能性的测试。当然事情肯定会变得越来越好,大家不都是说“有比没有好么”。

例二:LTP(Linux Test Project)。它可以测试很多东西,但也有很多地方它并不会去测试。它会被一些发行版使用,然后也肯定能在里面发现一些bug,但很明显我们需要更多更好的测试套件。

例三:性能测试(benchmark)和模糊测试(fuzzing)。会上还讨论了稳定内核的模糊测试。模糊测试上游内核是一种最好的选择,因为所有问题的修补都在那里,但它仍然可以在发行版的内核中发现问题。目前syzkaller fuzzer已经可以针对它发现的问题自动生成小的测试用例,大家也觉得这些应该被加入自检测试集。虽然有人提到一些BUG只在Kernel Address Sanitizer(缩写KASAN)下才会出现,但这些测试在那些没有被配置KASAN的内核上运行的时候是可以简单地被跳过的。除了找BUG的测试之外,内核还需要更多的性能测试来发现性能退化(performance regressions),有人提到可以用Mel Gorman的MMTests作为“kbench”这一性能测试套件的基础,只是这个套件对应的文档很少了,所以我们需要在内核文档目录中建立一个测试套件目录作为一个开始,但任何复杂的性能测试显然需要更加深入的文档。

例四:基准数字(single number)。有人提议说,如果我们有一个性能测试然后给出一个基准数字,而我们可以基于这个数字来判断性能是否有退化就完美了(比如BogoMips背后的想法),当然有另外一些人会质疑是否真的存在这样的测试系统。

例五:自我测试(self-tests)。越来越多的自我测试,正在被添加到内核主线中,但是稳定的内核却不会从中受益。有些人正在使用较老的内核进行最新的自我检测,于是有人提议也许自我测试本身应该被移植到稳定的内核树中。

例六:神经网络训练。随着BoF的结束,Levin要求发行版的维护者将他们正在使用的补丁推向稳定的分支中去。一般发行版中的问题在稳定内核中也一定存在。他最近一直在努力训练一个神经网络来识别适用于稳定内核的补丁,这引起了一些笑声,但他说结果是“出人意料的好”。

内核测试的一些其他声音

Greg Kroah-Hartman是稳定内核的维护者,他没有参加BoF但是其实对BoF的讨论内容也有兴趣。于是第二天当Levin在一个小型会议中概括总结BoF的讨论结果的时候,Greg给出了他的一些意见。

首先正如Levin所说,在BoF中大家提出了很多的观点,但是并没有什么相应的解决措施。有人建议应该向kernelci.org项目提供更多的硬件,Kroah-Hartman同时希望能看到更多的功能测试。另外还有一些人提议应该让Linaro和kernelci.org一起努力合作这样更好。

关于移植自我检测(self-tests),Kroah-Hartman并不反对这个想法,只要它们能在出问题的内核上运行就可以。他也同意如果发行版能将它们的修补补丁打在稳定的分支(tree)上,那将是一件很好的事情,而且他提到Fedora和Debian已经在该领域做得很好。另一位与会者表示,发行版经常会尽快为用户快速解决问题,然后才会做好上游内核的工作。 Kroah-Hartman表示,如果有BUG在上游内核中没有被修复的话,他也不会在稳定内核中修复,这样一方面上游内核和稳定内核做到了“bug兼容”,另一方面也给了那些厂商一些压力来修复它。

结语

我们需要进行更多的内核测试,这是毋庸置疑的,但是它究竟应该采用什么样的形式以及由谁来做仍然不清晰。如果幸运的话,在不久的将来这块会有一些进展,同时也意味着我们有可能会更早地发现BUG。当然,完美是不可能的,但是我们大家都希望能够减少内核里的错误,对么?另外一点,大家对于上游内核(upstream)的热情是远远高于稳定内核(stable)的,所以对于稳定内核的测试肯定仍然会比较少,所以稳定内核的“稳定性”是大打折扣的。

相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
相关文章
|
13天前
|
算法 Linux 调度
深入理解Linux内核调度器:从基础到优化####
本文旨在通过剖析Linux操作系统的心脏——内核调度器,为读者揭开其高效管理CPU资源的神秘面纱。不同于传统的摘要概述,本文将直接以一段精简代码片段作为引子,展示一个简化版的任务调度逻辑,随后逐步深入,详细探讨Linux内核调度器的工作原理、关键数据结构、调度算法演变以及性能调优策略,旨在为开发者与系统管理员提供一份实用的技术指南。 ####
51 4
|
17天前
|
缓存 算法 Linux
深入理解Linux内核调度器:公平性与性能的平衡####
真知灼见 本文将带你深入了解Linux操作系统的核心组件之一——完全公平调度器(CFS),通过剖析其设计原理、工作机制以及在实际系统中的应用效果,揭示它是如何在众多进程间实现资源分配的公平性与高效性的。不同于传统的摘要概述,本文旨在通过直观且富有洞察力的视角,让读者仿佛亲身体验到CFS在复杂系统环境中游刃有余地进行任务调度的过程。 ####
37 6
|
24天前
|
安全 Linux 虚拟化
|
2天前
|
缓存 网络协议 Linux
深入探索Linux操作系统的内核优化策略####
本文旨在探讨Linux操作系统内核的优化方法,通过分析当前主流的几种内核优化技术,结合具体案例,阐述如何有效提升系统性能与稳定性。文章首先概述了Linux内核的基本结构,随后详细解析了内核优化的必要性及常用手段,包括编译优化、内核参数调整、内存管理优化等,最后通过实例展示了这些优化技巧在实际场景中的应用效果,为读者提供了一套实用的Linux内核优化指南。 ####
11 1
|
8天前
|
算法 Linux 开发者
Linux内核中的锁机制:保障并发控制的艺术####
本文深入探讨了Linux操作系统内核中实现的多种锁机制,包括自旋锁、互斥锁、读写锁等,旨在揭示这些同步原语如何高效地解决资源竞争问题,保证系统的稳定性和性能。通过分析不同锁机制的工作原理及应用场景,本文为开发者提供了在高并发环境下进行有效并发控制的实用指南。 ####
|
16天前
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
45 9
|
15天前
|
缓存 负载均衡 Linux
深入理解Linux内核调度器
本文探讨了Linux操作系统核心组件之一——内核调度器的工作原理和设计哲学。不同于常规的技术文章,本摘要旨在提供一种全新的视角来审视Linux内核的调度机制,通过分析其对系统性能的影响以及在多核处理器环境下的表现,揭示调度器如何平衡公平性和效率。文章进一步讨论了完全公平调度器(CFS)的设计细节,包括它如何处理不同优先级的任务、如何进行负载均衡以及它是如何适应现代多核架构的挑战。此外,本文还简要概述了Linux调度器的未来发展方向,包括对实时任务支持的改进和对异构计算环境的适应性。
37 6
|
16天前
|
缓存 Linux 开发者
Linux内核中的并发控制机制:深入理解与应用####
【10月更文挑战第21天】 本文旨在为读者提供一个全面的指南,探讨Linux操作系统中用于实现多线程和进程间同步的关键技术——并发控制机制。通过剖析互斥锁、自旋锁、读写锁等核心概念及其在实际场景中的应用,本文将帮助开发者更好地理解和运用这些工具来构建高效且稳定的应用程序。 ####
35 5
|
16天前
|
算法 Unix Linux
深入理解Linux内核调度器:原理与优化
本文探讨了Linux操作系统的心脏——内核调度器(Scheduler)的工作原理,以及如何通过参数调整和代码优化来提高系统性能。不同于常规摘要仅概述内容,本摘要旨在激发读者对Linux内核调度机制深层次运作的兴趣,并简要介绍文章将覆盖的关键话题,如调度算法、实时性增强及节能策略等。
|
17天前
|
存储 监控 安全
Linux内核调优的艺术:从基础到高级###
本文深入探讨了Linux操作系统的心脏——内核的调优方法。文章首先概述了Linux内核的基本结构与工作原理,随后详细阐述了内核调优的重要性及基本原则。通过具体的参数调整示例(如sysctl、/proc/sys目录中的设置),文章展示了如何根据实际应用场景优化系统性能,包括提升CPU利用率、内存管理效率以及I/O性能等关键方面。最后,介绍了一些高级工具和技术,如perf、eBPF和SystemTap,用于更深层次的性能分析和问题定位。本文旨在为系统管理员和高级用户提供实用的内核调优策略,以最大化Linux系统的效率和稳定性。 ###