基础知识:LINUX下动态库加载相关知识
在LINUX 系统/etc 目录下有三个与动态库加载相关的文件,分别是ld.so.conf、ld.so.conf.d、ld.so.cache.
其中ld.so.conf中记录了程序在运行过程中需要加载的动态链接库(后缀名为.so的文件)的路径,默认情况下/lib路径和/usr/lib路径下的动态链接库会直接被包含到系统的搜索路径中,也就是说只要把动态库放到这两个目录中的任何一个,应用程序就可以直接调用,但是如果所有的动态库都放到这两个路径中,就会看起来很乱,而且后期升级动态库的时候也很难查找,因此需要将我们自己的动态库路径告诉系统,最简单的方法就是修改ld.so.conf文件,假如我的动态库文件放在/usr/local/lib路径下,只要我们在ld.so.conf的末尾加上一句/usr/local/lib即可,系统就会在运行应用程序时自动搜索该路径下有没有需要的库文件。
ld.so.cache是ld.so.conf的缓存文件,我们在修改完ld.so.conf文件后,要执行一下/sbin/ldconfig指令,该指令的需要在root用户下执行,作用是重新加载ld.so.conf的内容到ld.so.cache文件中供系统使用,如果不执行该命令,则新添加的动态路路径不会生效。
ld.so.conf.d 是一个文件夹,该文件夹里面是各种动态库路径的配置文件,这些文件里记载了动态库的搜索路径。我们打开ld.so.conf文件后可以看到里面只有一句内容:include /etc/ld.so.conf.d/*.conf 意思就是使用ld.so.conf.d文件夹下的所有配置文件中记录的路径作为动态库搜索路径。
使用ldconfig -p 可以查看系统中所有的动态链接库,如果要查看某个应用程序依赖于那个动态库,可以使用ldd指令,例如我们想要查看/home/hello 依赖于那个动态库可以输入 ldd /home/hello 进行查看。
添加动态库搜索路径除了修改ld.so.conf文件外还有以下方法,其加载优先级如下:LD_PRELOAD>LD_LIBRARY_PATH>/etc/ld.so.cache>/lib>/usr/lib
使用LD_PRELOAD环境变量设置加载路径的优先级更高,应用程序在检索依赖的动态库时会优先使用LD_PRELOAD环境变量中设置的检索路径下的动态库文件。其次是环境变量LD_LIBRARY_PATH ,再其次是修改/etc/ld.so.conf,然后是/lib,最后是/usr/lib,利用这种优先级关系,可以在替换动态库文件时,使用高优先级配置方法进行设置,这样应用程序就会优先加载自己替换的动态库文件。使用方法如下: LD_PRELOAD=/usr/local/hello.so
现在我们来介绍下C库:
C库顾名思义就是运行C语言需要依赖的库文件,没有这个库文件,C语言就运行不起来。常用的C库有ANSI C库和GUN C 库两种,其中ANSI C 库使用C标准化组织定义的,特点是不依赖平台,在LINUX 下可以使用,在WINDOWS下也可以使用,GUNC 库是专门用于LINUX系统下的C运行库。
一般我们在编写应用程序时尽量使用ANSI C 库,否则一旦需要将应用程序进行跨平台移植,就会有很多麻烦。
以下时ANSI C 库包含的相关头文件:
<ctype.h>:包含用来测试某个特征字符的函数的函数原型,以及用来转换大小写字母的函数原型;
<errno.h>:定义用来报告错误条件的宏;
<float.h>:包含系统的浮点数大小限制;
<math.h>:包含数学库函数的函数原型;
<stddef.h>:包含执行某些计算 C 所用的常见的函数定义;
<stdio.h>:包含标准输入输出库函数的函数原型,以及他们所用的信息;
<stdlib.h>:包含数字转换到文本,以及文本转换到数字的函数原型,还有内存分配、随机数字以及其他实用函数的函数原型;
<string.h>:包含字符串处理函数的函数原型;
<time.h>:包含时间和日期操作的函数原型和类型;
<stdarg.h>:包含函数原型和宏,用于处理未知数值和类型的函数的参数列表;
<signal.h>:包含函数原型和宏,用于处理程序执行期间可能出现的各种条件;
<setjmp.h>:包含可以绕过一般函数调用并返回序列的函数的原型,即非局部跳转;
<locale.h>:包含函数原型和其他信息,使程序可以针对所运行的地区进行修改。
地区的表示方法可以使计算机系统处理不同的数据表达约定,如全世界的日期、时间、美元数和大数字;
<assert.h>:包含宏和信息,用于进行诊断,帮助程序调试。
在Linux平台上最广泛使用的C函数库是glibc
,其中包括C标准库的实现,也包括本书第三部分介绍的所有系统函数。几乎所有C程序都要调用glibc
的库函数,所以glibc
是Linux平台C程序运行的基础。glibc
提供一组头文件和一组库文件,最基本、最常用的C标准库函数和系统函数在libc.so
库文件中,几乎所有C程序的运行都依赖于libc.so
,有些做数学计算的C程序依赖于libm.so
,以后我们还会看到多线程的C程序依赖于libpthread.so
。以后我说libc
时专指libc.so
这个库文件,而说glibc
时指的是glibc
提供的所有库文件。
glibc 库作为LINUX系统最底层的库,几乎所有的C应用程序的运行都依赖这个库文件,我们在编译运行C应用程序时就不可避免的牵扯到版本的问题,比如当执行某一应用程序时,系统提示glibc版本过低,这时候就需要升级glibc库。
1. 下载解压
glibc库下载地址:/gnu/glibc/
2. 执行configure 生成Makefile (注意执行configure的路径不能在glibc路径下,可以到其他路径下使用绝对路径命令执行)
/home/configure \
CC=arm-none-linux-gnueabi-gcc \
CXX=arm-none-linux-gnueabi-g++ \
--prefix=/home/glibc \
--target=arm-linux --host=arm-linux
3. make && make install
4. 修改环境变量,更新glibc 库搜索路径
//添加环境变量
vim /etc/profile
//在文件里加入这一行,保存退出
export LD_LIBRARY_PATH = $LD_LIBRARY_PATH:/home/glibc-2.17/lib
//使之生效 source /etc/profile