库:可执行的二进制代码,不可以独立执行(没有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. SPA路由实现的基本原理

    1. SPA路由实现的基本原理 前端单页应用实现路由的策略有两种,分别是 基于hash 和 基于 History API 基于hash 通过将一个 URL path 用 # Hash 符号拆分.- 浏 ...

  2. python中time模块的常用方法的转换关系图

    获取当前的时间戳 把时间戳转换成了时间的格式 获取时间 把时间格式数据转换为易识别的字符串 获取到表示时间的字符串,再转换为时间数据.

  3. PYTHON编写程序练习-打印99乘法表

    使用for循环嵌套的知识点编写 for i in range(1,10):   #第一层循环,循环乘数 for j in range(1,i+1):   #第二层循环,循环被乘数 print(f&qu ...

  4. cximage菜单(Mirror)

    // ID_CXIMAGE_MIRROR 文件:CxImage\demo\demoDoc.cpp 菜单项:cximage->Mirror ON_COMMAND(ID_CXIMAGE_MIRROR ...

  5. dismount ASM磁盘组,影响未使用的其它ASM磁盘组

    # 问题概述登录数据库,查看活动会话,发现大量library cache lock ,log file switch (archiving needed),归档失败,redo log无法重用.# 问题 ...

  6. 支持管道、重定向、*匹配的miniShell

    先上成果图 源代码 仅供技术点的分享,抄袭者就算了,所以main.c就不贴了 /* * split_line.c */ #include <stdio.h> #include <st ...

  7. Docker 架构演进之路

    转载:https://developer.aliyun.com/article/673009 前言 Docker已经推出了5年,在这5年中它极大的改变了互联网产品的架构,推进了新的产品开发.测试和运维 ...

  8. [网鼎杯2020]boom

    [网鼎杯2020]boom 分析 感觉比较友善,主要考查数学运算. 解析 解压之后发现是个exe文件,运行得到一个md5 查询: 输入明文得到: 下个挑战是解三元一次方程: 拿matlab算一下. s ...

  9. Vulnhub:vulnuni1.0.1靶机

    kali:192.168.111.111 靶机:192.168.111.192 信息收集 端口扫描 nmap -A -v -sV -T5 -p- --script=http-enum 192.168. ...

  10. Mybatis学习笔记【狂神说】

    环境 Jdk 1.8 Mysql 5.7 Maven 3.6.1 IDEA 回顾 JDBC Mysql java基础 Maven Junit SSM框架:都是有配置文件的.最好的学习方式:看官方文档. ...