库:可执行的二进制代码,不可以独立执行(没有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. Linux练习题--打印文本第10行

    文本test.txt,需要打印文本第10行 方法一: sed -n '10p' test.txt 说明:sed命令使用-n参数时,只有经过sed 特殊处理的那一行(或者动作)才会被列出来. 命令&qu ...

  2. 一篇文章让你了解这个基于树莓派而设计的工业计算机-CM4 Industrial

    CM4 Industrial是一款基于 Raspberry Pi / 树莓派 Compute Module 4,由EDATEC面向工业应用设计的嵌入式计算机设计的工业嵌入式计算机.系统可以根据不同的应 ...

  3. Vulhub 漏洞学习之:ECShop

    Vulhub 漏洞学习之:ECShop 目录 Vulhub 漏洞学习之:ECShop 1 ECShop 2.x/3.x SQL注入/远程命令执行漏洞 1.1 环境安装 1.2 漏洞产生原因 1.3 漏 ...

  4. 探索 C 语言的递归函数

    <C Primer Plus>函数章节:递归函数.结合 Visual Studio 调试理解 C 语言的递归函数,下面是书上一模一样的代码,贴在这里: #include<stdio. ...

  5. Postgresql invalid command \N数据恢复处理

    做一个单表恢复工作,数据在1000多W,说是报了错误导不进去,环境与流程见下:恢复步骤: 1.导出语句 pg_dump -h xxxxx -p 5432 -U postgres -b -Fp db_t ...

  6. 开源分布式任务调度系统就选:DolphinScheduler

    分布式任务调度这个话题是每个后端开发和大数据开发都会接触的话题.因为应用场景的广泛,所以有很多开源项目专注于解决这类问题,比如我们熟知的xxl-job. 那么今天要给大家推荐的则是另一个更为强大的开源 ...

  7. Ansible介绍以及基于角色搭建LNMP和zabbix

    1 ansible 常用指令总结,并附有相关示例. /usr/bin/ansible 主程序,临时命令执行工具 /usr/bin/ansible-doc 查看配置文档,模块功能查看工具,相当于man ...

  8. Visual Studio 2022 不支持 .NET Framework 老版本 项目解决办法

    Visual Studio 2022 不支持 .NET Framework老版本 (4.5) 项目解决办法 新电脑安装的是Visual Studio 2022,打开老项目的时候发现没有.net fra ...

  9. CF1303F 题解

    题意 传送门 有一个 \(n\times m\) 的矩阵,初始全是 \(0\).我们定义 \(a_{i,j}\) 表示矩阵中第 \(i\) 行第 \(j\) 列的元素. 如果两个格子有相邻边并且格子中 ...

  10. 生成brobuff

    xxx_pb.js需要服务端打包好 再新建export.js文件 var IMBaseDefine= require('./xxx_pb'); module.exports = { DataProto ...