这是我在做计算实验程序时碰到的一个小问题。场景是这样的,自己的机器上运行的是ubuntu8.10,gcc 4.2,也经常apt-get update。用于运行计算任务的是学院的一台IBM cluster 1350服务器,上面的系统是 rhel3。在ubuntu下编辑编译好程序,将执行文件放入服务器上运行。出问题之前,在程序中没有#include <stdlib.h>,ubuntu下的程序在rhel3上运行良好。加了#include <stdlib.h>后,在rhel3中运行出现问题 /lib/tls/libc.so.6: version `GLIBC_2.4' not found 。问题是小问题,但也学了不少知识,看下面分析过程。
分析一,stdlib.h包文件包含在那个包中?glibc是GNU c函数库,这提供给我们编写c代码的大部分库函数,这个stdlib.h也在其中咯。但是rhel3上也是有glibc的,yum -qa|grep glibc,是glibc-2.3.2-95.30,低于2.4,但为什么出现了版本依赖问题呢?已知信息:编辑和编译的平台是ubuntu,运行的平台是redhat,系统兼容问题;ubuntu的包都被我时常更新,redhat 则是e as3,里面的包比较旧。按照这样的思路,在redhat上安装了glibc_2.4的包后,程序如期能够运行。还有东西可学,继续...
分析二,既然开始认为不同linux之间,可能出现问题,那么就找了另外一台redhat系统,redhat as4, glibc.2.3.4,高于服务器的glibc-2.3.2。将程序在redhat as4上编译成执行文件,拷贝到redhat as3上运行,也可以正常运行。哎?这个为什么就行了!可见不同linux系统之间的编程环境差别性有待进一步学习。
分析三,既然是包依赖的问题,那么看看是否可以避免这个包依赖。在编译时采用的是动态连接的方式,如果采用静态连接的编译,会不会就好了。加入/usr/lib/libc.a,得到了比原来大许多的执行文件,拷入redhat as3上,依然出现同样问题;加入-static /usr/lib/libc.a,得到的执行文件还要更大一些,放入redhat as3上执行,反馈是 “FATAL: kernel too old Segmentation fault ” 。静态连接的含义是什么?静态连接编译出的执行文件在执行的时候,调用包含在头文件里的库函数的顺序规则是什么?Linux中静态链接与动态链接涉及到Linux共享函数库。共享函数库是为了供开发方便和减少冗余,里面包含了常用的函数。动态链接得到的执行文件在执行的时候,会动态调用库中的函数,它的执行文件中没有包含库函数的实体,因而执行文件相应就会小些;而静态链接则是将要调用的库中函数链接到执行文件当中,这样执行文件中就有一份库函数拷贝了,在执行的时候就不用去调用共享库中的函数而是直接使用这份拷贝,但文件相应会大了许多。依照此分析,我用-static(这个参数禁止使用了共享库,所以不用关心共享库而直接执行)编译出的文件,在redhat as3上执行的反馈是kernel too old,说明了在执行我的执行文件时,kernel版本和glibc版本之间还出现了冲突。(PS:在google "fatal:kernel too old"得到的大多数文档中,是问在编译内核时出现了这个错误,回答是和glibc相关)那么内核和glibc的关系有是什么呢?[6]
关于glibc的文件解释
[1]
http://blog.csdn.net/My_emdebed/archive/2007/04/22/1574746.aspx静态链接libc的一个例子
[2]
http://www.9php.com/FAQ/cxsjl/c/2007/04/704307080637.html进一步了解静态链接和动态链接
[3]
http://cmdblock.blog.51cto.com/415170/86802gcc笔记
[4]
http://www.cublog.cn/u/13991/showart.php?id=96714 [5]
http://www.bloghome.cn/posts/10410 GCC,glibc,kernel的要点//Linux发布程序要注意版本的软件包
[6]http://www.linux-cn.com/html/linux/network/20080818/57908.html