Linux glibc 问题
相信有不少 Linux 用户都碰到过运行第三方(非系统自带软件源)发布的程序时的 glibc 兼容性问题,这一般是由于当前 Linux 系统上的 GNU C 库(glibc)版本比较老导致的,例如我在 CentOS 6 64 位系统上运行某第三方闭源软件时会报:
[root@liangxu ~]# ldd tester./tester: /lib64/libc.so.6: version `GLIBC_2.17' not found (required by ./tester)./tester: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./tester) linux-vdso.so.1 => (0x00007ffe795fe000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc7d4c73000) libOpenCL.so.1 => /usr/lib64/libOpenCL.so.1 (0x00007fc7d4a55000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fc7d4851000) libm.so.6 => /lib64/libm.so.6 (0x00007fc7d45cd000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fc7d43b7000) libc.so.6 => /lib64/libc.so.6 (0x00007fc7d4023000) /lib64/ld-linux-x86-64.so.2 (0x00007fc7d4e90000)
CentOS 6 自带的 glibc 还是很老的 2.12 版本,而下载的第三方程序依赖 glibc 2.17 版本,这种情况要么自己重新编译程序,要么只能升级系统的 glibc 版本。由于我使用的程序是第三方编写并且是闭源软件无法自己编译,升级 glibc 固然可能能解决问题,但是 glibc 做为最核心的基础库,在生产环境上直接升级毕竟动作还是太大,因此希望还是能有更好的解决途径。
问题分析
首先我们可以检查一下程序使用了新版本 glibc 的哪些符号,使用 objdump 命令可以查看 ELF 文件的动态符号信息:
[root@liangxu ~]# objdump -T tester | grep GLIBC_2.1.*0000000000000000 DF *UND* 0000000000000000 GLIBC_2.14 memcpy0000000000000000 DF *UND* 0000000000000000 GLIBC_2.17 clock_gettime
从上面的输出可以看到程序使用了 glibc 2.14 版本的 memcpy 函数和 glibc 2.17 版本的 clock_gettime 函数,而这两个常用的函数按说应该是 glibc 很早就已经支持了的,我们可以确认一下当前系统 glibc 提供的符号版本:
[root@liangxu ~]# objdump -T /lib64/libc.so.6 | grep memcpy0000000000091300 w DF .text 0000000000000009 GLIBC_2.2.5 wmemcpy0000000000101070 g DF .text 000000000000001b GLIBC_2.4 __wmemcpy_chk00000000000896b0 g DF .text 0000000000000465 GLIBC_2.2.5 memcpy00000000000896a0 g DF .text 0000000000000009 GLIBC_2.3.4 __memcpy_chk[root@liangxu ~]# objdump -T /lib64/libc.so.6 | grep clock_gettime000000000038f800 g DO .bss 0000000000000008 GLIBC_PRIVATE __vdso_clock_gettime
这里可以看出 CentOS 6 的 glibc 库提供的 memcpy 实现是 2.2.5 版本的,另外 libc 没有直接实现 clock_gettime 函数,因为老版本 glibc 里 clock_gettime 是由 librt 库提供 clock_gettime 支持的,而且同样也是 2.2.5 版本:
[root@liangxu ~]# objdump -T /lib64/librt.so.1 | grep clock_gettime000000000