Aki*_*ain 2 drivers kernel-modules linux-kernel proprietary-drivers
为什么 Linux 模块 API 不向后兼容?更新 Linux 内核后,我对找到更新的驱动程序感到沮丧。
我有一个需要专有驱动程序的无线适配器,但制造商在大约 7 年前停产了该设备。由于代码很旧并且是为 Linux 2.6.0.0 编写的,因此不能使用最新的 Linux 内核进行编译。我使用过许多 Linux 发行版,但同样的问题无处不在。尽管有一个随 Linux 内核分发的开源驱动程序,但它不起作用。有些人试图修改旧的专有代码以使其与最新的 Linux 内核兼容,但是当发布新的 Linux 内核时,使代码与之兼容需要数月时间。在此期间,发布了另一个新版本。因此,我无法升级到新的 Linux 内核;有时我什至无法升级我的发行版。
尽管我已经为 Linux 内核贡献了一些(非常小的)补丁,但我并不认为自己是内核开发人员。然而,这是我所知道的:
为内核版本 2.6.0.0 编写的驱动程序早于内核版本 2.6.39 中发生的大内核锁 (BKL) 的消除。
BKL 是在 Linux 仍然是单处理器(单核、单线程)操作系统时创建的。一旦添加了 SMP 支持,开发人员就意识到 BKL 会在某个时候成为一个大瓶颈,但只要系统中总共只有几个内核/线程,这还是可以忍受的。但对于在超级计算机中使用 Linux 的人来说,它首先成为一个真正的问题,因此工作开始用更细粒度的锁定机制或尽可能用无锁方法替换所有需要 BKL 的东西。
在现代计算机上,普通台式机和大功率笔记本电脑可能有两位数的内核,更不用说服务器了,2.6.0 向后兼容的内核模块 API 也需要实现 BKL。
如果遗留模块说“我想使用 BKL”,则内核的其余部分不知道该模块打算用它做什么,因此向后兼容机制将不得不使用所有替换 BKL 的锁只是为了涵盖所有的可能性。那将是一个巨大的性能打击。并且新的无锁方法还需要检查遗留锁——这首先破坏了无锁的意义。因此,即使没有实际加载遗留模块,向后兼容机制的存在也会降低系统性能。
最近,Spectre/Meltdown 安全补丁对跨越内核/用户空间边界时需要发生的事情进行了重大更改。在实施 Spectre/Meltdown 修复之前编译的任何模块对于 post-Specre/Meltdown 内核都可能不可靠。
就在两周前,我正在对一台旧服务器进行故障排除,当自动化应用安全更新时,该服务器需要手动重启。这种情况之前已经发生过多次,并且可以重现。我发现它megasr在 Spectre/Meltdown 补丁之前有一个非常旧的专有存储驱动程序版本,它没有包含在自动更新中。将驱动程序更新到当前版本后,问题就消失了。顺便说一下,这是在一个普通的 RHEL 6.10 系统上。
我还看到服务器在使用 post-Spectre/Meltdown 内核加载专有的 pre-Spectre/Meltdown 硬件监控驱动程序时崩溃。基于这种经验,我完全相信 Spectre/Meltdown 修复需要被视为一个分水岭事件:内核和模块需要要么全部是修复前的版本,要么全部是修复后的版本;混合和匹配只会导致值班系统管理员的悲痛和午夜叫醒电话。
而且由于 Spectre 是CPU 设计级别的问题,因此它是“不断给予的礼物”:有些人会找到新的方法来利用弱点,然后内核开发人员将需要找出阻止漏洞的方法。
这些只是 2.6.0.0 兼容的遗留内核模块 API 需要解决的两个大问题。我相信还有很多其他的。
然后还有更哲学的一面。想一想:是什么让 Linux 成为可能?
其中很大一部分是开放的硬件规范。如果硬件规格公开,任何人都可以参与。由于操作系统的源代码是开放的,任何人都可以贡献,造福于所有人。如果您的驱动程序代码是开源的,您就不能将硬件编程规范作为您的商业机密。
Linux 内核开发人员倾向于相信开源模型。这就是为什么他们做出了他们的设计和开发选择,以便硬件制造商参与的首选方式是开源驱动程序,将其合并到主要内核源代码分发中,然后(只有这样)您才能在维护它时从整个内核开发人员社区中受益。
这为硬件设计人员和制造商提供了一些激励,使之成为可能。如果您有一些想要保密的东西,请努力将其封装到 ASIC 中,或者如果必须的话,也可以封装到签名固件中。(如果你做后者,请授予他人重新分发固件包的权限。)
但是由于内核是开源的,内核开发者不能完全阻止其他人单独维护专有驱动程序。但他们也没有动力去关心他们。
事实上,内核调试中专有二进制驱动程序造成的额外麻烦是内核开发人员不关心专有驱动程序开发的诱因:“它们使我的工作更加困难,为什么我要特别做任何事情来使他们的工作更容易?”
因此,内核开发人员通常会做对他们作为一个团体/社区最有利的事情。如果这包括一些模块 API 更改,那就这样吧。第三方驱动程序甚至没有进入等式。
Greg Kroah-Hartman 在此处撰写了有关此主题的文章:https ://www.kernel.org/doc/html/v4.10/process/stable-api-nonsense.html
除了有关编译 C 代码的一些技术细节之外,他还提出了几个做出决定的基本软件工程问题。
Linux 内核始终在进行中。发生这种情况的原因有很多:
大多数软件都是如此,任何没有维护的软件都会缓慢而痛苦地死去。您要问的是为什么那些旧的未维护代码仍然有效?
为了确保向后兼容性,需要维护旧的(通常是“损坏的”和不安全的)接口。当然,这在理论上是可能的,除非它确实带来了巨大的成本。
格雷格·克罗-哈特曼写道
如果 Linux 必须确保它保留一个稳定的源接口,就会创建一个新的接口,而旧的、损坏的接口将不得不随着时间的推移而维护,从而为 [开发人员] 带来额外的工作。由于所有 Linux [开发人员] 都在自己的时间工作,要求程序员无偿、免费地做额外的工作是不可能的。
尽管 Linux 是开源的,但开发人员维护它的时间仍然有限。所以人力还是可以从“成本”的角度来讨论的。开发人员必须选择他们如何度过他们的时间:
总的来说,合并接口确实具有成本效益(对于内核开发人员)。如果您想知道为什么开发人员不花费数月甚至数年的时间来帮助其他人免于为新的 wifi 适配器支付 10 美元……这就是原因。请记住,这对内核开发人员来说是时间/成本有效的,对您或制造商来说不一定是成本有效的。
| 归档时间: |
|
| 查看次数: |
414 次 |
| 最近记录: |