静态库与动态库(共享库)
(一)静态库与动态库(共享库)的区别:
-
1)静态库:
在程序的链接阶段被复制到了程序中(GCC进行连接时,会把静态库中代码打包到可执行程序中去) -
2)动态库:
①程序在运行时由系统被动加载到内存中供程序调用(注:在链接阶段没有被复制到程序中,即动态库的代码不会打包到可执行程序中)
②需要系统的动态载入器获取所依赖的库文件的绝对路径,对于elf格式的可执行程序,是由ld-linux.so 来完成的, 先搜索elf文件的DT_RPATH****段(在系统为进程分配的虚拟地址空间中,无法操作)->环境变量 LD_LIBRARY_PATH -> /etc/ld.so.cache****文件列表 -> /lib/, /usr/lib****目录找到库文件后将其载入内存**
③利用 ldd 命令 可以检查动态库依赖关系:
利用 env 命令 可以查看环境变量:
配置动态库的方式:
1. 通过修改环境变量配置动态库的方式
-
临时
将动态库加载到环境变量中(临时生效,重启后失效)( /a为动态库的路径地址 )
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a
-
永久
①用户级别的配置
在/home目录下修改 .bashrc 文件, 具体步骤如下:
step1 用vim打开 ~/.bashrc 文件
vim ~/.bashrc
step2 在 .bashrc文件最后一行插入动态库的路径地址( /a为动态库的路径地址 )
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a
step3 保存并退出 .bashrc文件后,运行下面命令实现修改生效
. ~/.bashrc
前面的 . 就是 source的意思,所以也可以写成
source ~/.bashrc
②系统级别的配置:
step1 用vim打开/etc/profile文件
sudo vim /etc/profile
step2 在profile文件最后一行插入动态库的路径地址( /a为动态库的路径地址 )
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/a
step3 保存并退出profile文件,运行下面命令实现修改生效
source /etc/profile
或者也可以写成
. /etc/profile
2.通过修改/etc/ld.so.cache文件列表配置动态库的方式
直接修改 /etc/ld.so.cache文件列表是无法操作的,因为该文件列表为二进制代码,因此一般通过 sudo vim /etc/ld.so.conf 间接修改,具体步骤如下:
step1 打开ld.so.conf文件
sudo vim /etc/ld.so.conf
step2 将动态路径保存在该文件里面
step3 保存并退出,更新配置
sudo ldconfig
3.通过将动态库文件直接放入 /lib 或/usr/lib目录
不推荐,容易出现自定义库文件名称与系统自带库文件名称冲突,从而覆盖原有系统库文件
(二)动态库和静态库的制作、编译、运行
1.动态库的制作、编译、运行
制作
- gcc得到 .o 文件,得到和位置无关的代码
gcc -c -o main.o main.c -fpic/-fPIC
gcc -c -o sub.o sub.c -fpic/-fPIC
- gcc得到动态库
gcc -shared -o libsub.so sub.o sub2.o sub3.o(可以使用多个.o生成动态库)
编译
gcc -o test main.o -lsub -L /libsub.so/所在目录/
运行
运行时,要确保动态库已在指定目录
./test
2.静态库的制作、编译、运行
制作
- gcc获得 .o 文件
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
- 将 .o 文件打包,使用 ar 工具(archive)
ar crs libsub.a sub.o sub2.o sub3.o(可以使用多个.o生成静态库)
编译
gcc -o test main.o libsub.a (如果.a文件不在当前目录下,需要指定它的绝对或相对路径)
运行
运行时,不需要把静态库文件放到嵌入式开发板上
./test
3.-fpic与-fPIC对比分析:
相同点
都是为了在动态库中生成位置无关的代码。通过全局偏移表(GOT)访问所有常量地址。程序启动时动态加载程序解析GOT条目
不同点
如果链接的可执行文件的GOT大小超过计算机特定的最大大小,则会从链接器收到错误消息,指示-fpic不起作用;在这种情况下,请使用-fPIC重新编译。GOT大小根据操作系统的不同而大小不一样,SPARC上为8k,在AArch64上为28k,在m68k和RS / 6000上为32k。x86没有此限制
总结
为了兼容各个系统,在生成位置无关的代码的时候,应该使用-fPIC参数