参考文档
- http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
- http://man7.org/linux/man-pages/man8/ld.so.8.html
- The Linux Programming Interface chapter 41
原理
glibc
glibc提供了系统级的c语言库(也叫libc6),其他版本libc已基本被淘汰。现在Linux编译程序都依赖用glibc2编译,小版本号已经到了glibc2.23。
so文件的加载
glibc2编译的程序,如果要加载so文件,都是由/lib64/ld-linux-x86-64.so.2
完成的。例如/bin/ls -l
的运行,其实是执行了
/lib64/ld-linux-x86-64.so.2 /bin/ls -l
so文件加载顺序
- LD_LIBRARY_PATH
- /etc/ld.so.cache
- /lib,/usr/lib for 32bit OS
- /lib64,/usr/lib64 for 64bit OS
指定so加载目录
gcc -g -Wall -Wl,-rpath,/home/mtk/pdir -o prog prog.c libdemo.so
gcc -Wl,-rpath,'$ORIGIN'/lib ...
指定dynamic linker
g++ main.o -o myapp ... \
-Wl,--rpath=/path/to/newglibc \
-Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2
可以通过这个命令看gcc的默认值
% gcc -dumpspecs
......
*link:
...%{m16|m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}}...
......
ld.so.cache
so文件被缓存在/etc/ld.so.cache
里,用ldconfig -p
可以打印出来
ldconfig和ld.so.conf
ldconfig
会把/etc/ld.so.conf
描述的so文件,放入/etc/ld.so.cache
so文件存放位置
- /usr/lib ,ubuntu或centos的库放在这里
- /lib,开机就需要的库放在这里
- /usr/local/lib, 用户自己编译的代码
相关环境变量
LD_LIBRARY_PATH=xxx command #指定so文件目录
LD_PRELOAD=xx.so command #指定提前加载的so,这些会override默认的so文件
LD_DEBUG=help commond
LD_DEBUG=files commond #显示verbose信息
LD_DEBUG=bindings commond #显示符号绑定
LD_DEBUG=libs commond #显示search path
LD_DEBUG=versions command #显示版本依赖
LD_DEBUG=all commond
加载时候是动态link
编译动态链接库时候,需要制定-fPIC
参数
- PIC : position-independent code
安装so文件
- copy so file to /usr/lib
- 根据soname建立符号链接
- run ldconfig
目录
- /lib 系统启动的时候依赖的库,/lib被mount比较早
- /usr/lib 一般都安装在这里
- /usr/local/lib,非标准的,或者用户自己编译的体验版
- /etc/ld.so.conf描述的目录
Tools
ldd
ldd会至少2个so
- ld-linux.so.2 : the dynamic linker
- libc.so.6 : the standard C library
ldd /bin/ls
nm
搜索哪个lib有crypt函数定义
# nm -A /usr/lib/lib*.so 2> /dev/null | grep ' crypt$'
/usr/lib/libcrypt.so:00007080 W crypt
ldconfig
- 搜索一个so,需要很久,ldconfig帮忙引入cache => /etc/ld.so.cache
- 更新so库时候,需要运行ldconfig
ldconfig -p #display the cache
ldconfig -v #修改so后,会显示变化
so的版本管理
引入soname概念
- libdemo.so.1.0.1
- libdemo.so.1.0.2 主版本没变化,小版本有变化,和以前兼容
- libdemo.so.2.0.0 主版本变化,因此和以前不兼容
soname一般设置成libname.so.major-id,如
- libdemo.so.1 -> libdemo.so.1.0.2
- libdemo.so.2 -> libdemo.so.2.0.0
- libreadline.so.5 -> libreadline.so.5.0
so文件的兼容性
Application Binary Interface (ABI)
查看glibc版本
/lib64/libc.so.6
ldd --version
strings /lib64/libc.so.6 |grep GLIBC_
https://benohead.com/linux-check-glibc-version/
安装多版本glibc
使用patchelf
https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host/851229#851229
替换新库
例如替换glibc,先编译好glibc
rm /lib64/libc.so.6
ln -s /lib64/libc-2.17.so /lib64/libc.so.6