Ianus Inferus/地狱门神

Exoptatus infera advenisti.

View on GitHub Go Back

Linux上的glibc版本兼容性问题

Ianus Inferus

2021-11-16

在Linux上,glibc的版本兼容性问题是广为人知的。不像Windows上的kernel32.dll,glibc既是一个操作系统接口(POSIX),又是一个C标准库(C99, C11等),而且它是向下兼容而不是向上兼容的,即旧系统上编译的程序可以运行在新系统上,而反过来不行。这导致Linux上发布二进制程序非常困难。

静态链接

那么能不能将glibc静态链接到程序里呢?答案是不太行,因为glibc和系统结合过于紧密,会动态调用NSS等功能。参见这个问题

但换一个C标准库就可以了,比如说musl或者uClibc-ng。有一些现成的工具链可用,比如说基于gcc和musl的工具链musl-cross-makemusl libc toolchain。不过换C标准库并静态链接存在一些问题:

编译时使用较老的glibc

可以直接在一个glibc较老的系统上编译程序,但存在一些问题:

另外一种方法是将老系统制作成sysroot,然后进行交叉编译。可以从老系统的系统分区或者安装镜像提取需要的文件。这种方法也是Google的Android NDK使用的方法。获取sysroot的方法详见笔者另外的文章How to Get Sysroot for clang。存在下列问题:

最后,还有一种方法是使用glibc_version_header,可以强制编译时使用较旧的glibc符号。存在下列问题:

其他

一般使用的最老的glibc为CentOS 6.x带的glibc 2.12。

顺带一提,docker不是这个问题的解决方案。因为glibc依赖于Linux内核版本,只能在一个机器上运行使用同样或者更旧的内核的docker镜像。在这种情况下,其实可以直接在物理机上运行程序。

Go Back