ABI

系统调用、符号版本与数据结构演进:FreeBSD 如何处理兼容性

| Kernel | #FreeBSD | #ABI | #libc | #Programming

操作系统在演进过程中经常会碰到一个很现实的问题:一方面,内核和基础系统不可能几十年保持原样, 数据结构会变,系统调用会增加,某些早期设计也迟早需要推倒重来;另一方面,一个已经发布出去的 ABI 又不能想改就改。如果几十年间内核里的数据结构换了一批又一批,这艘船究竟还是不是当年那艘船? 保证它在用户态眼里仍然是同一艘船的关键,就在于 ABI 的稳定性。 否则系统每升级一次,过去编译好的程序都有可能需要重新编译,整个生态很快就会变得难以维护。

FreeBSD 在这方面有一个比较有利的条件:内核和基础用户态程序都在同一个源代码树中开发, 因此,一次涉及 kernel/userland ABI 的修改,通常可以同时修改系统调用、libc、 头文件以及基础系统中的调用者。

不过,这并不意味着兼容性会自动得到保证;恰恰相反,大多数兼容性最终仍然要靠一些相当具体、 甚至有些繁琐的工程手段来维持。

FreeBSD 对稳定分支上的用户态 ABI 非常重视,并将其视为一项核心特性。 项目的架构支持政策明确提到,对于 Tier 1 平台上的 userland ABI 变化, 通常应当提供兼容层,使针对任一稳定分支编译的程序无需重新编译或修改, 仍然能够正确运行(不过,某些兼容层可能并不在默认安装中启用)。 换句话说,ABI 稳定并不是一句抽象的承诺,它最终会落实成 libc 里的版本符号、 内核里的旧系统调用入口,以及各种名字里带着 freebsd11freebsd12 的兼容代码。

这些代码单独看往往并不复杂,真正麻烦的是它们一旦成为 ABI 的一部分,就很难轻易删除。

阅读全文…( 本文约 4740 字,阅读大致需要 10 分钟 )