背景

最近工作中遇到个问题,就是多个系统跑着不同版本的内核,不同架构的ARM芯片,上层的业务程序能否二进制归一(共镜像)。

根据自己对Linux的了解,glibc是否可以在ABI层面做到向前兼容。那个整个系统能否做到呢?这勾起了我的分析和思考。

ABI兼容依赖什么

试想一下,一个程序从源代码到最终的二进制,有哪些组件参与了编译和链接过程,大概如下:

  • 内核导出用户态头文件
  • gcc编译器,gcc提供的静态.o/.a,以及它提供的动态库(如libgcc_s.so)
  • glibc
  • 第三方开源库

需要分析各组通能否做到二进制兼容性,以及是如何做到的。下面我对各组件,以思维导图来分析是否能满足ABI兼容性。

axios升级兼容性 abi兼容性_axios升级兼容性

上面的思维导图把我想到的组件都进行细分,把每个细节都覆盖到。当然,还会有一些细节是我没有想到的。下面对不那么常见的组件进行说明:

  • 内核导出头文件: 构建过交叉编译工具链是嵌入式里面常做的事情,工具链的构建需要使用内核导出的导文件。这是内核态和用户约定好的基础类型和数据结构,比如我们常见的time_t,pid_t等等类型。整于用户态软件都以它为基石。
  • glibc版本机制:glibc对大部分符号都打上版本号,日后在高版本的glibc中,由于POSIX/LSB标准的变化,或者函数接口有变,它会创建该符号的另一新版本,但原来版本的符号仍然存在,同时语义和参数保持不变。它通过这种机制来保证ABI的向前兼容性(请注意,无法保证向后的兼容性)

从分析来看,大部分软件都是可以保持向前兼容的。这就是为什么从一台机制上的程序拷贝到另一台机制上,程序还能正常运行。

Linux standard Base(LSB)

噢,这到底是巧合呢?还是什么:所有Linux 程序都是在所有机器上运行。我也带个着这个问题去找一些资料。
想信大家听说到POSIX规范,Linux Standard Base(LSB)规范。起初,我以为LSB是API规范而非ABI规范。当我去深入分析时,发现它是一个ABI规范,它解决两方面的问题:

  • 在发行版Linux A上运行的程序,可以运行在发行版本Linux B上。
  • 应用程序在现在的机器上运行,也能在未来新系统和机器上运行。

最近Linux基金会发起LSB项目就是希望Linux发行商能做到相互兼容,并且也能向前兼容。解决Linux应用的可移植性和兼容性。

LSB实际是是一组ABI接口的定义,它规范了运行环境所需要的类型,宏,变量和函数的二进制接口。

那么,哪些东西受到LSB的制约呢?也即LSB规范约束的范围多广。刚开始,我还以为只有kernel, glibc等一些关键的组件。事实上,打开LSB官网说明会发现它包罗万象,从命令,ELF,glibc接口,到桌面,脚本语言等等都有相关的规定。

谁应该遵守LSB规范

毫无疑问,kernel, glibc等都应该遵守LSB标准。事情上,并非如此。 LSB希望Linux发布版(如Redhat, Suse, Ubuntu)能遵守LSB,因此它提供了LSB的测试套和LSB的认证服务。

那么Kernel和glibc就真的不需要考虑LSB了吧,答案是否定的。整个kernel/glibc和各大Linux知名组件都以开源方式进行开发,它里面的技术早已不是什么密秘了,各大公司都有工程师参与,所有公司都希望这些软件都是遵守LSB,使所有软件都能轻易地融合在一起,不希望让发生行商花很大力气去集成。因此所有软件都是会尽量遵守LSB规范,但无法排除有那么一两个例外的Case。

glibc是大家用得最多的组件,也算是我比较了解的组件之一,到网上找了一些它的兼容性分析,发现它也不能保证100%向前兼容。不能完全兼容的发生在2.16.0和2.13两个版本上。当前对于一般的软件,这个兼容性是完全足够了的。

“向后”兼容性

那么Linux能做到向后兼容性吗?答案是否定的,因为LSB也无法做到向后兼容。

那问题来了,如果我需要做到向后兼容呢?假如有下面这种场景:

很多服务器都是Ubuntu 7.04,算是8年前的服务器了,数量很多。同时也会有服务器使用了12.04,数量较少。但12.04上的编译器较新,支持很多安全功能。架构师的诉求就是:能否基于12.04版本运行环境做开发编译,生成的服务程序能同时运行在7.04和12.04两个服务器上。

我能想到的解决办法:

  • 找到Ubuntu 7.04和12.04两服务器运行软件,所遵守的LSB版本,服务程序只能调用这两LSB完全兼容的接口
  • 在编程和链接服务程序时,可以指定程序使用的LSB标准(Ubuntu 7.04版本的LSB)。

对于第一个方法,个人认为可行,但约束很多。方法二未知可行,后续再分析

这就是“向后”兼容性想讨论的一个问题。它不是真正的向后兼容性,完全是依赖于向前兼容来实现的。

后记

兼容性,完全不是我熟悉的东西,只是工作上遇到问题,做了初步分析。希望通过blog记录我的思考,当某一天,我对这个知识有深入的经验,再跟大家分享。如有写得不正确,或者误导的内容,请指正,谢谢!