库:可执行的二进制代码,不可以独立执行(没有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 动态库、静态库的更多相关文章

  1. c/c++:动态库 静态库 linux/windows 例子 (转)

    作者:吴秦出处:http://www.cnblogs.com/skynet/本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接). C++静 ...

  2. 在Linux中创建静态库.a和动态库.so

    转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...

  3. Linux 下动态库 / 静态库(依赖)

    一. 依赖动态库的动态库 libfun.so依赖动态库libtest.so(libfun.so动态库里的函数intnothing()调用了libtest.so里的intmytest()函数),而mai ...

  4. Linux库函数制作(静态库、动态库)

    Linux库函数制作(静态库.动态库) 静态库与动态库 链接方式 链接分为两种:静态链接.动态链接 静态链接: 由链接器在链接时将库的内容加入到可执行程序中 静态链接的特点是: 优点: 对运行环境的依 ...

  5. linux+vs2013编译静态库和动态库

    Linux下创建与使用静态库 Linux静态库命名规则 Linux静态库命名规范,必须是"lib[your_library_name].a":lib为前缀,中间是静态库名,扩展名为 ...

  6. linux 动态库 静态库 函数覆盖

    本文讨论了linux动态库  静态库中函数的覆盖问题. 测试目的: 同名函数,分别打成动态库libdync_lib.so与静态库libstatic_lib.a,并把libstatic_lib.a打到另 ...

  7. Linux 动态库 静态库

    什么是库 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.由于windows和Linux的本质不同,因此二者库的二进制是不兼容的.Linux操作系统支持的库函数分为静态库和动态库 ...

  8. linux下的静态库和动态库

    一.linux下的静态库   静态库中的被调用的函数的代码会在编译时一起被复制到可执行文件中去的!!可执行文件在运行不需要静态库的存在!   二.linux下动态库的构建和使用 1.动态库的构建   ...

  9. linux下的静态库创建与查看,及如何查看某个可执行依赖于哪些动态库

    linux下的静态库创建与查看,及如何查看某个可执行依赖于哪些动态库   创建静态库:ar -rcs test.a *.o查看静态库:ar -tv test.a解压静态库:ar -x test.a 查 ...

  10. Linux中的静态库与动态库

    什么是库文件? 库文件是事先编译好的方法的合集.比如:我们提前写好一些数据公式的实现,将其打包成库文件,以后使用只需要库文件就可以,不需要重新编写. Linux系统中: 1.静态库的扩展名为.a:2. ...

随机推荐

  1. 微信小程序数字转中文wxs

    场景: 传入数字,转换成天数,比如:index = 1 转换后则为 一,在页面中的应用就是<view>第{{index}}天</view>,转为第几天. <view> ...

  2. 自动化测试如此容易!多语言自动化测试框架 Selenium 编程(C#篇)

    介绍 Selenium 官网:https://www.selenium.dev/ Selenium 是功能强大的自动化测试工具集,是支持 Web 浏览器自动化的一系列工具和库的总括项目,一共包括以下三 ...

  3. 什么是MES(Manufacturing Execution System)

    "本文仅代表个人观点" 本文档将提供一个高层次的概述,以帮助阐明什么是MES,并触及通常被归为MES的周边领域. 整体情况 制造执行系统或MES软件是旨在帮助公司管理其制造过程的工 ...

  4. select加下拉箭头

    <div class="flex"> <label>城市</label> <div class="dealerbo"& ...

  5. 微信小程序防止多次点击提交的方法

    Page({ data: { lock: false }, //表单提交 submit(){ let that = this; let {lock} = that.data; if(!lock){ t ...

  6. 昇腾AI新技能,还能预防猪生病?

    摘要:日前,由华为与武汉伯生科技基于昇腾AI合作研发的"思符(SiFold)蛋白质结构预测平台"正式推出,并成功应用于国药集团动物保健股份有限公司的猪圆环病毒疫苗研发中. 本文分享 ...

  7. Linux操作命令(九)1.comm命令 2.diff命令 3.patch命令

    1.comm 命令 比较文本文件的内容 comm 命令将逐行比较已经排序的两个文件.显示结果包括 3 列:第 1 列为只在第一个文件中找到的行,第 2 列为只在第二个文件中找到的行,第 3 列为两个文 ...

  8. Eureka服务治理

    Eureka是由Netflix开发的一款服务治理开源框架,Spring-cloud对其进行了集成.Eureka既包含了服务端也包含了客户端,Eureka服务端是一个服务注册中心(Eureka Serv ...

  9. [WPF]MVVM的数据绑定

    啥是MVVM? 我理解的MVVM是Model(数据),View(界面),ViewModel(数据与界面之间的桥梁)的缩写,是一种编程模式.前期需要多花一些时间去编辑绑定,在后期维护方便.只需要关注数据 ...

  10. 【狂神说】SpringMVC笔记

    1.回顾MVC ssm:mybatis+Spring+SpringMVC MVC三层架构 ssm框架:研究官方文档,锻炼自学能力,锻炼项目能力 SpringMVC+Vue+SpringBoot+Spr ...