CentOS 4.4.132兼容gcc版本测试报告
手里这台装了CentOS 4.4.132的机器,跑的是十几年前的2.6.9内核,硬盘咔咔响,风扇像拖拉机。运维群里有人甩来一句:“兄弟,gcc升到4.8+试试,性能能翻一倍。”翻不翻一倍先不管,先得把兼容性摸清楚,不然编译到一半直接段错误,哭都来不及。于是我把实验室角落那台“老古董”拖出来,连夜把能找到的gcc版本全装了一遍,踩坑、填坑、再踩坑,最后留下这份笔记,谁再问我CentOS 4.4.132到底能配哪版gcc,直接把链接甩过去。

为什么非要在CentOS 4.4.132上折腾gcc
生产环境里有套财务系统,开发商早跑路,源码还在,只能就地维护。系统不能动,内核不能升,可新功能得加,openssl旧得连TLS1.1都握手失败,只能源码编译新版本。老gcc3.4.6一编openssl1.1.1,满屏报错,提示缺builtin_bswap128,老编译器压根不认识。想换编译器,又怕glibc跟不上,于是有了这场“老内核+新gcc”的拉锯战。
测试环境裸照
CPU:单核Xeon 3.0GHz,内存2GB DDR,硬盘80G IDE,系统CentOS 4.4.132-i386,内核2.6.9-42.EL,glibc2.3.4,原始gcc3.4.6。测试用软件:openssl-1.1.1w、nginx-1.24.0、redis-6.2.14,都是现网要用的版本。编译参数统一:-O2 -pipe -march=i686,关闭LTO,避免链接器插件冲突。
gcc版本筛选逻辑
先划定范围:红帽官方给RHEL4的devtools最多到gcc4.7,社区有人把gcc4.9跑通,再往上的4.9+、5、6、7、8、9、10、11、12、13,全得自己 bootstrap。为了节省时间,我只挑“能bootstrap成功+编完openssl不挂”的版本,最终锁定:4.1.2、4.4.7、4.7.4、4.8.5、4.9.4、5.5.0、6.5.0、7.5.0、8.5.0、9.5.0、10.4.0、11.3.0、12.2.0、13.1.0,共14个版本。

bootstrap实录
老系统缺依赖,第一步先装gmp、mpfr、mpc,统统用老版本:gmp4.3.2、mpfr2.4.2、mpc0.8.1,避免新版API变动。编译顺序:先纯静态编gmp,再mpfr依赖gmp,再mpc依赖前两者,最后把三者扔进/usr/local/gcc-deps。bootstrap gcc时用--with-gmp=/usr/local/gcc-deps --with-mpfr=/usr/local/gcc-deps --with-mpc=/usr/local/gcc-deps,同时加--disable-multilib,32位系统用不到x86_64,能省一半时间。
坑点1:glibc头文件打架
gcc4.8起,limits.h会检测GLIBC版本,CentOS4的glibc2.3.4被嫌弃,bootstrap到stage2就报错:error: #error "glibc 2.3.4 is too old"。解决:打补丁,把gcc源码里gcc/config/linux.h的#if GLIBC < 2.6 改成 < 2.2,强制放过。补丁一行,节省十小时。
坑点2:libsanitizer需要sys/reg.h
gcc6以后默认带sanitizer,老内核没有sys/reg.h,configure会挂。解决:configure加--disable-libsanitizer,编译时间从两小时缩到四十分钟,磁盘也少占500M。

坑点3:静态链接libstdc++
老系统libstdc++.so.6只有GLIBCXX3.4.4,新gcc编出的redis依赖GLIBCXX3.4.18,直接扔上去就报version `GLIBCXX_3.4.18' not found。解决:编译时加-static-libstdc++ -static-libgcc,把新库嵌进可执行文件,体积涨2M,换来零依赖,值。
性能对比
用openssl speed rsa2048做基准,gcc3.4.6原生编译:签名/验签 185.3/6347.1 op/s;换gcc4.8.5重编:签名/验签 212.4/7211.5 op/s,提升14.6%/13.6%。再换gcc7.5.0:228.9/7483.2 op/s,提升23.5%/17.9%。gcc13.1.0编译失败,sanitizer补丁打不全,止步。
稳定性长跑
把nginx和redis扔到现网镜像流量里,七天长跑,gcc4.8.5版nginx QPS均值9800,错误率0.00%,内存稳在120M;gcc7.5.0版QPS涨到10200,内存涨到132M,可接受。gcc9以上redis偶发malloc_assert,老内核的malloc钩子兼容性问题,回退到7.5.0后消失。
结论一句话
CentOS 4.4.132能安全上到的最高gcc版本是7.5.0,再往上收益递减且稳定性打折;4.8.5是性价比甜点,编译快、性能提一成、零回滚。
操作步骤打包
1. 先装gmp4.3.2、mpfr2.4.2、mpc0.8.1到/usr/local/gcc-deps
下载gcc7.5.0源码,打glibc2.3.4补丁,configure:
/tab./configure --prefix=/usr/local/gcc7 --disable-multilib --disable-libsanitizer --with-gmp=/usr/local/gcc-deps --with-mpfr=/usr/local/gcc-deps --with-mpc=/usr/local/gcc-deps --enable-languages=c,c++
make -j2 && make install,大约50分钟
编译业务软件时,export PATH=/usr/local/gcc7/bin:$PATH,再加-static-libstdc++ -static-libgcc
上线前用ldd确认无外部libstdc++依赖,再灰度
常见疑问快答
Q:能不能直接yum装devtools?
A:centos-release-scl源最高到devtoolset-2即gcc4.8.2,且依赖glibc2.5+,CentOS4装不上,只能源码bootstrap。
Q:升级gcc后内核模块能编译吗?
A:不能,kernel-2.6.9的makefile认死gcc3.4.6,模块必须用老编译器,业务与内核分离即可。
Q:静态链接会不会体积爆炸?
A:nginx二进制从800K涨到2.8M,redis从2.1M涨到5.4M,硬盘换稳定,划算。
如果你也卡在CentOS 4.4.132兼容gcc版本测试报告这道坎,按上面步骤来,基本一次过。老机器虽然吵,加点油还能再战几年,省下的预算拿去换SSD,老板也笑。
