linux 动态库、静态库
库:可执行的二进制代码,不可以独立执行(没有main函数入口)
库是否兼容:取决于编译器、汇编器、链接器
linux链接静态库(.a):将库中用到的函数的代码指令,写入到可执行文件中、运行时无依赖
linux链接动态库(共享库.so):在可执行程序中记录了库中函数的符号表信息,执行时再找库,找不到,则无法执行。
程序默认使用动态库
1、静态库
静态库命名:libxxx.a,在编译的第4步使用,链接阶段
1.1制作静态库:
(1)gcc -c xxx.c -o xxx.o //.c文件制作成.o文件 gcc -c 只编译,不链接,生成目标文件
(2)ar -rcs libxxxx.a xxx.o aaaa.o //使用ar工具制作静态库。ar是linux压缩备份命令,可以将多个文件打包成一个备份文件
(3)编译链接库 gcc test.c -o a.out libxxxx.a
(4)ar -t 查看libxxxx.a是由哪些.o文件构成。
ar -t 显示静态库的内容
ar -d 从库中删除成员文件
ar -r 在库中加入成员文件,若存在,则替换
ar -c 创建一个库
ar -s 无论ar命令是否修改了库内容,都强制重新生成库符号表
1.2 静态库示例
main.c 源码


[root@localhost test_lib]# cat main.c
#include <stdio.h> int main()
{
int a = 2,b = 3,c = 0;
printf("c = %d\n", test_lib_a(a,b));
printf("c = %d\n", test_lib_b(a,b));
printf("c = %d\n", test_lib_c(a,b));
return 0;
}
test_lib_a.c、test_lib_b.c、test_lib_c.c源码


[root@localhost test_lib]# cat test_lib_a.c
#include <stdio.h> int test_lib_a(int a, int b)
{
printf("%s\n", __FUNCTION__);
return a + b;
}
[root@localhost test_lib]#
[root@localhost test_lib]# cat test_lib_b.c
#include <stdio.h> int test_lib_b(int a, int b)
{
printf("%s\n", __FUNCTION__);
return a + b;
}
[root@localhost test_lib]# cat test_lib_c.c
#include <stdio.h> int test_lib_c(int a, int b)
{
printf("%s\n", __FUNCTION__);
return a + b;
}
[root@localhost test_lib]# cat test_lib_a.c
#include <stdio.h> int test_lib_a(int a, int b)
{
printf("%s\n", __FUNCTION__);
return a + b;
}
[root@localhost test_lib]#
[root@localhost test_lib]# cat test_lib_b.c
#include <stdio.h> int test_lib_b(int a, int b)
{
printf("%s\n", __FUNCTION__);
return a + b;
}
[root@localhost test_lib]# cat test_lib_c.c
#include <stdio.h> int test_lib_c(int a, int b)
{
printf("%s\n", __FUNCTION__);
return a + b;
}
编译.c 查看生成的.o文件
[root@localhost test_lib]# gcc -c *.c
[root@localhost test_lib]# ls
libtest_lib_all.a main.c main.o test_lib_a.c test_lib_a.o test_lib_b.c test_lib_b.o test_lib_c.c test_lib_c.o
[root@localhost test_lib]# ar -rcs libtest_lib.a test_lib_a.o test_lib_b.o test_lib_c.o
[root@localhost test_lib]# gcc main.o -o a.out libtest_lib.a
[root@localhost test_lib]# ./a.out
test_lib_a
c = 5
test_lib_b
c = 5
test_lib_c
c = 5
这三种方式编译也ok


[root@localhost test_lib]# gcc test_lib_a.o test_lib_b.o test_lib_c.o main.o -o a.out //这种编译也ok
[root@localhost test_lib]#
[root@localhost test_lib]# gcc test_lib_a.o test_lib_b.o test_lib_c.o main.c -o a.out //这种编译也ok [root@localhost test_lib]# gcc main.c -o a.out libtest_lib.a
2、动态库
.so 库 (Shared Object ),共享的目标文件
查看文件(动态库)的依赖 : ldd xxxxx
2.1 制作动态库
[root@localhost test_lib]# gcc -shared -fPIC -c *.c //需要带-shared -fPIC编译,否则无法做成动态库
// gcc -shared -fPIC -o libxxxx.so bbbb.o cccc.o dddd.o
[root@localhost test_lib]# gcc -shared -fPIC -o libtest_lib.so test_lib_d.o test_lib_b.o test_lib_c.o
2.2 动态库示例
test_lib_d.c 代码


[root@localhost test_lib]# cat test_lib_d.c
#include <stdio.h> int test_lib_a(int a, int b)
{
printf("%s but this test_lib_c.c\n", __FUNCTION__);
return a + b;
}
编译 .o 编译 .so
[root@localhost test_lib]# gcc -shared -fPIC -c *.c //编译.o 文件
[root@localhost test_lib]# gcc -shared -fPIC -o libtest_lib.so test_lib_d.o test_lib_b.o test_lib_c.o //编译动态库
// 查看编译生成的动态库.so和.o文件
[root@localhost test_lib]# ls
a.out lib_path libtest_lib.so main.c main.o test_lib_a.c test_lib_a.o test_lib_b.c test_lib_b.o test_lib_c.c test_lib_c.o
运行可执行文件
[root@localhost test_lib]# cp lib_path/libtest_lib.so /lib64/ //将库拷贝到动态库默认搜索路径/lib64下
[root@localhost test_lib]# ./a.out
test_lib_a but this test_lib_c.c
c = 5
test_lib_b
c = 5
test_lib_c
c = 5
3、链接库、链接头文件
-I(大写i):指定include包含文件的搜索路径.
-L :指定链接所需库所在路径
-l(小写L):指定所需链接库的库名(比如链接libastatic.a) -lastatic
-static: :静态链接,但会导致所有的库都使用静态连接
-Wl,-Bdynamic:指明为动态链接
-Wl,-Bstatic:指明为静态链接
-Wl,-rpath=:指定文件搜索库路径
混合链接时:动态库在静态库前面链接时,必须在命令行最后使用动态连接的命令。(系统的运行库使用动态链接方式,结尾不是动态链接,会导致后面链接系统的库,去找到的是静态库)
混合链接时:优先链接动态库
如下为证明优先链接动态库
//编译生成静态库、动态库
[root@localhost test_lib]# ar -rcs libtest_lib_b.a test_lib_b.o
[root@localhost test_lib]# ar -rcs libtest_lib_c.a test_lib_c.o
[root@localhost test_lib]# gcc -shared -fPIC -o libtest_lib_a.so test_lib_d.o
// 动态库、静态库混合链接,且证明优先链接动态库
[root@localhost test_lib]# gcc main.c -o a.out -L lib_path/ -Wl,-Bdynamic -ltest_lib_a -Wl,-Bstatic -ltest_lib_b -ltest_lib_c -Wl,-Bdynamic
[root@localhost test_lib]#
[root@localhost test_lib]# ./a.out
./a.out: error while loading shared libraries: libtest_lib_a.so: cannot open shared object file: No such file or directory
[root@localhost test_lib]# mv lib_path/libtest_lib_a.so /lib64/
[root@localhost test_lib]#
[root@localhost test_lib]# ./a.out
test_lib_a but this test_lib_c.c
c = 5
test_lib_b
c = 5
test_lib_c
c = 5
//静态链接放在结尾,是有问题的
[root@localhost test_lib]# gcc main.c -o a.out -L lib_path/ -Wl,-Bdynamic -ltest_lib_a -Wl,-Bstatic -ltest_lib_b -lte st_lib_c
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
[root@localhost test_lib]# [root@localhost test_lib]# gcc main.c -o a.out -L lib_path/ -Wl,-Bstatic -ltest_lib_b -ltest_lib_c -Wl,-Bdynamic -lte st_lib_a
3.1、解决动态库链接问题
./a.out: error while loading shared libraries: libtest_lib.so: cannot open shared object file: No such file or directory
上面问题核心原因是,编译时候能链接到动态库,可执行文件执行时找链接不到库。
解决办法1:
1、拷贝库到默认链接路径下,即拷贝库到/lib、/lib64、/usr/lib下 |
2、编译时,指定库运行时库搜索路径。即加上前缀-Wl(小写L), -R(或-rpath)。-Wl,-rpath=./lib_path -L./lib_path |
3、环境变量LD_LIBRARY_PATH指定的动态库搜索路径。export LD_LIBRARY_PATH=./lib_path |
4、配置文件/etc/ld.so.conf中指定的动态库搜索路径 |
[root@localhost test_lib]# gcc main.c -o a.out -Wl,-rpath=./lib_path -L./lib_path -ltest_lib
3.2、库链接顺序
注意:库的链接顺序为从左到右,即A依赖B,则-lA -lB。越基础的库越放在右边
4、查看库的属性:
(1)ldd xxxx //查看xxx文件的依赖库
(2)已经启动的,查看进程号,cat /proc/PID/maps //可以查看到可执行文件已加载的库
(3)xxx-linux-objdump -x file-name | grepp NEEDED
(4)xxx-linux-readelf -a file-name | grep Shared
参考:
https://www.cnblogs.com/xingmuxin/p/11416518.html
https://zhuanlan.zhihu.com/p/349122842
https://blog.csdn.net/JoshYueby/article/details/105528682
https://blog.csdn.net/yueguangmuyu/article/details/117655920
linux 动态库、静态库的更多相关文章
- c/c++:动态库 静态库 linux/windows 例子 (转)
作者:吴秦出处:http://www.cnblogs.com/skynet/本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接). C++静 ...
- 在Linux中创建静态库.a和动态库.so
转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...
- Linux 下动态库 / 静态库(依赖)
一. 依赖动态库的动态库 libfun.so依赖动态库libtest.so(libfun.so动态库里的函数intnothing()调用了libtest.so里的intmytest()函数),而mai ...
- Linux库函数制作(静态库、动态库)
Linux库函数制作(静态库.动态库) 静态库与动态库 链接方式 链接分为两种:静态链接.动态链接 静态链接: 由链接器在链接时将库的内容加入到可执行程序中 静态链接的特点是: 优点: 对运行环境的依 ...
- linux+vs2013编译静态库和动态库
Linux下创建与使用静态库 Linux静态库命名规则 Linux静态库命名规范,必须是"lib[your_library_name].a":lib为前缀,中间是静态库名,扩展名为 ...
- linux 动态库 静态库 函数覆盖
本文讨论了linux动态库 静态库中函数的覆盖问题. 测试目的: 同名函数,分别打成动态库libdync_lib.so与静态库libstatic_lib.a,并把libstatic_lib.a打到另 ...
- Linux 动态库 静态库
什么是库 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.由于windows和Linux的本质不同,因此二者库的二进制是不兼容的.Linux操作系统支持的库函数分为静态库和动态库 ...
- linux下的静态库和动态库
一.linux下的静态库 静态库中的被调用的函数的代码会在编译时一起被复制到可执行文件中去的!!可执行文件在运行不需要静态库的存在! 二.linux下动态库的构建和使用 1.动态库的构建 ...
- linux下的静态库创建与查看,及如何查看某个可执行依赖于哪些动态库
linux下的静态库创建与查看,及如何查看某个可执行依赖于哪些动态库 创建静态库:ar -rcs test.a *.o查看静态库:ar -tv test.a解压静态库:ar -x test.a 查 ...
- Linux中的静态库与动态库
什么是库文件? 库文件是事先编译好的方法的合集.比如:我们提前写好一些数据公式的实现,将其打包成库文件,以后使用只需要库文件就可以,不需要重新编写. Linux系统中: 1.静态库的扩展名为.a:2. ...
随机推荐
- vue的异步组件
异步组件 异步组件:可以在首页加载之前先加载的组件,主要是做性能优化,提高用户体验 一.基本用法 在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件.Vue 提供了 de ...
- 消息传递(news)题解
代码 #include<cstdio> #include<algorithm> using namespace std; const int N = 200000; int f ...
- SP2416 DSUBSEQ - Distinct Subsequences
题意 求本质不同的子串个数(包括空串) 思路 序列自动机裸题 直接上代码 \(Code\) #include<cstdio> #include<cstring> using n ...
- [EULAR文摘] TNFi治疗3年对384例强柱患者脊柱放射学进展的影响
TNF拮抗剂治疗3年对384例强直性脊柱炎患者脊柱放射学进展的影响 Maksymowych WP, et al. EULAR 2015. Present ID: OP0144. 背景: 既往开放标签的 ...
- MySQL索引相关知识学习心得
你知道的越多,你不知道的也就越多 -- 芝诺曾 一.MySQL索引学习 MySQl主要有两种类型的索引:哈希索引.B+树索引 1.哈希索引 哈希索引可以以O(1)的时间复杂度进行查找,但是这样查找导致 ...
- CF873E - Awards For Contestants
题意:对于 \(n\) 个人,每个人有一个分数,现在要把所有人分成四等,使得: 前三类都有人 前三类中,任意类的人数不大于其他类的人数的两倍 不能有 \(i\) 的分数比 \(j\) 高但是所属的等级 ...
- .Net DI(Dependency Injection)依赖注入机制
1.简介 DI:Dependency Injection,即依赖注入,他是IOC的具体实现. 在DI中,底层服务对象不再负责依赖关系的创建,而是交由顶端调用进行管理注入 好处:降低组件之间的耦合度,使 ...
- PKU2506Tiling
https://blog.csdn.net/Harington/article/details/86612106
- Java后台校验手机号和邮箱
//true是手机号,false不是手机号 public static boolean checkPhone(String phone){ Pattern p = Pattern.compile(&q ...
- djangoDRF查询
DRF全部查询基础示例 from django.db.models import Q, F, Sum, Avg, Count, Min, Max from rest_framework.respons ...