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;
}
View Code

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;
}
View Code

编译.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
View Code

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;
}
View Code

编译 .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

posted on 2022-07-01 14:45  红旗kernel  阅读(368)  评论(0编辑  收藏  举报

导航