静态库与动态库文件的制作与使用

静态库与动态库

什么是库文件?

  • 提供变量,函数/类的封装的代码仓库

  • 不能单独运行 而一般的程序文件可以单独运行

  • 分为静态库和动态库

  • 好处: 代码保密 方便部署和分发

动态库与静态库的区别

静态库在程序链接阶段被复制到程序中, 动态库在程序运行时由系统定位动态库文件并加载到内存中使用

image-20211130112706895

库类型 优点 缺点
静态 打包到应用程序中加载速度快 消耗系统资源,浪费内存
发布程序无需提供静态库,移植方便 更新、部署、发布麻烦
动态 可以实现进程间资源共享(共享库)
更新、部署、发布简单 加载速度比静态库慢 运行时需要查找库再加入
可以控制何时加载动态库 发布程序时需要提供依赖的动态库

命名规则

静态库

Linux: libxxx.a 只有xxx是自定义

Windows:libxxx.lib xxx自定义

动态库

Linux:libxxx.so

Windows:libxxx.dll

库的制作与使用

静态

r 将文件插入备存文件(备存文件?)

c 建立备存文件索引

s 索引

gcc  a.c b.c -o a.o b.o
ar rcs libxxx.a a.o b.o

当前文件

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# tree
.
├── add.c
├── div.c
├── head.h
├── libcalc.a
├── main.c
├── mult.c
└── sub.c

编译成目标文件

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# gcc -c add.c div.c mult.c sub.c 
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o

创建静态库

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# ar rcs libcalc.a  sub.o div.o mult.o add.o
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/calc# tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── libcalc.a
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o

使用静态库

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# tree
.
├── include
│   └── head.h
├── lib
│   └── libcalc.a
├── main.c
└── src
    ├── add.c
    ├── div.c
    ├── mult.c
    └── sub.c

编译main程序头文件

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# gcc main.c -o app
main.c:2:10: fatal error: head.h: No such file or directory
    2 | #include "head.h"
      |          ^~~~~~~~
compilation terminated.

提供了头文件 但找不到定义的内部内容

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# gcc main.c -o app -I ./include/
/usr/bin/ld: /tmp/ccmLoZI5.o: in function `main':
main.c:(.text+0x3e): undefined reference to `add'
/usr/bin/ld: main.c:(.text+0x60): undefined reference to `subtract'
/usr/bin/ld: main.c:(.text+0x82): undefined reference to `multiply'
/usr/bin/ld: main.c:(.text+0xa4): undefined reference to `divide'
collect2: error: ld returned 1 exit status

提供静态库

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# gcc main.c -o app -I ./include/ -l calc -L ./lib/

执行程序

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession05/library# ./app
a = 20, b = 12
a+b= 32
a-b= 8
a*b= 240
a/b= 1.666667

动态

ldd list dynamic dependencies 检查依赖

定位共享库文件

知道库的名字不够,它会先后搜索elf文件的 DT_RPATH段 ——> 环境变量
LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib/,/usr/lib
目录找到库文件后将其载入内存

  • 使用LD_LIBRARTY_PATH
  • 使用/lib/, /usr/lib/

动态库制作

├── calc
│   ├── add.c
│   ├── div.c
│   ├── head.h
│   ├── main.c
│   ├── mult.c
│   └── sub.c
└── library
    ├── include
    │   └── head.h
    ├── lib
    │   └── libcalc.so
    ├── main
    ├── main.c
    └── src
        ├── add.c
        ├── div.c
        ├── mult.c
        └── sub.c

生成位置无关代码

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/calc# gcc -c -fpic add.c div.c mult.c sub.c
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/calc# tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o

生成共享动态库

root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/calc# gcc -shared *.o -o libcalc.so
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/calc# tree
.
├── add.c
├── add.o
├── div.c
├── div.o
├── head.h
├── libcalc.so
├── main.c
├── mult.c
├── mult.o
├── sub.c
└── sub.o

使用动态库

├── include
│   └── head.h
├── lib
│   └── libcalc.so
├── main
├── main.c
└── src
    ├── add.c
    ├── div.c
    ├── mult.c
# gcc main.c -o main -I ./include/ -L ./lib/ -l calc
# ldd main  查看依赖关系

提示无法找到共享库时

使用以下三种方法 定位动态库文件 因为动态库是在最后加入内存

环境变量LD_LIBRARY_PATH

export LD_LIBRARY_PATH = $LD_LIBRARY_PATH : /root/Linux/lession06/library/lib  暂时的环境变量 重启终端后删除
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/library# ldd
ldd: missing file arguments
Try `ldd --help' for more information.
root@iZwz953bcwdl9hfnde2odsZ:~/Linux/lession06/library# ldd main
        linux-vdso.so.1 (0x00007ffc1cd4d000)
        libcalc.so => /root/Linux/lession06/library/lib/libcalc.so (0x00007f7a5f3bf000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7a5f1c6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f7a5f3cb000)

vim .bashrc 用户级别永久环境变量
最后插入export LD_LIBRARY_PATH = $LD_LIBRARY_PATH : /root/Linux/lession06/library/lib
. .bashrc或者source .bashrc
vim /etc/profile  系统级别环境变量
下同上

配置/etc/ld.so.cache文件列表

二进制文件无法直接修改 因此间接

# vim /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
/root/Linux/lession06/library/lib 插入的内容
posted @ 2021-12-15 23:03  LeoSharh  阅读(228)  评论(0编辑  收藏  举报