Linux 静态库和动态库原理 区别 制作和使用

本文详细介绍了Linux环境下静态库和动态库的概念、制作方法、使用方式及其优缺点。静态库在编译时会被整合到程序中,而动态库在运行时动态加载。静态库加载速度快,移植方便,但会占用更多内存;动态库则实现资源共享,便于更新和部署,但加载速度相对较慢。
摘要由CSDN通过智能技术生成

1、什么是库

库文件是计算机上的一类文件,提供给使用者一些开箱即用的变量、函数或类。静态库和动态库,静态库和动态库的区别体现在程序的链接阶段:静态库在程序的链接阶段被复制到了程序中;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。

假设当前目录下有以下文件

├── main.c

├── tools.c

└── tools.h

tools.h 包含get_sum函数的声明

#ifndef tools_h
#define tools_h
int get_sum(int a,int b);
#endif /* tools_h */

tools.c 包含get_sum函数的定义

int get_sum(int a, int b){
    return a+b;
}

main.c 需要使用到get_sum函数

#include <stdio.h>
#include "tools.h"

int main(){
    printf("%d\n",get_sum(12,12));
    return 0;
}

2、静态库

在程序的链接阶段被复制到了程序中,编译完后就不再需要引入的库了。

2.1 命名规则

在Linux平台下:libxxx.a

​ libxxx.a:库文件的名字

​ lib:前缀(固定)

​ xxx:库的名字,自己起

​ .a:后缀(固定)

windows:libxxx.lib

2.2 制作方法

tools.c

int get_sum(int a, int b){
    return a+b;
}

tools.h

#ifndef tools_h
#define tools_h
int get_sum(int a,int b);
#endif /* tools_h */

上述源文件包含一个求和函数,现在我们想把它打包成一个库供其他程序使用。

  1. 获得.o文件

    使用-c参数,只生成汇编程序,不进行链接

    gcc -c tools.c
    
  2. 将.o文件打包,使用ar工具(archive)

    ar rcs libtools.a tools.o
    

    r:将文件插入备存文件中,即libtools.a

    c:create,创建备存文件

    s:缩引

2.3 使用方法

此时文件结构:

├── libtools.a

├── main.c

├── tools.c

├── tools.h

└── tools.o

为了测试调用库中的文件,现在删除tools.c,tools.o,但不能删除tools.h,使用静态库来编译程序的时候需要用到,tools.h中保存了库文件中函数的定义。

现在目录结构:

├── libtools.a

├── main.c

└── tools.h

现在使用库文件libtools.a来编译main.c,需要指定-I(大i),-l -L参数

-I(大i,Include):指定头文件路径

-l :库的名字

-L:库文件的路径

$ gcc main.c -o app -I ./ -l tools -L ./

3、动态库

3.1 命名规则

Linux:libxxx.so

​ lib:前缀(固定)

​ xxx:库的名字

​ .so:后缀(固定)

​ 在Linux下是一个可执行文件

windows:libxxx.dll

3.2 制作方法

假设此时目录结构:

├── main.c

├── tools.c

└── tools.h

内容和1、一致

  1. 获得和位置无关的.o文件,需要添加 -fpic参数,在某些平台可能需要-fPIC

    $ gcc -c -fpic tools.c
    

    生成tools.o

  2. 获得动态库

    $ gcc -shared tools.o -o libtools.so
    

现在动态库就制作好了,此时目录结构:

├── libtools.so

├── main.c

├── tools.c

├── tools.h

└── tools.o

3.3 使用方法

  1. 编译main.c

    -I(大i,Include):指定头文件路径

    -l :库的名字

    -L:库文件的路径

    $ gcc main.c -o app -I ./ -l tools -L ./
    
  2. 运行app

    $ ./main$ ./app./app: error while loading shared libraries: libtools.so: cannot open shared object file: No such file or directory
    

    此时报错了,原因是没有找到动态库,此时需要手动置顶动态库的地址。

  3. ldd,该命令可以查看一个程序的依赖关系,即需要导入哪些动态库

    $ ldd ./app	linux-vdso.so.1 (0x00007ffdab47f000)	libtools.so => not found	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd4861ad000)	/lib64/ld-linux-x86-64.so.2 (0x00007fd4867a0000)
    

    可以看到,运行该程序需要libtools.so,此时显示未找到。

  4. 指定动态库路径

    假设动态库所在路径为/home/so

    临时指定,只在当前终端有效,关闭了或其他终端都不可用。

    $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/so
    

    长期指定

    # 将上述命令写入用户的配置文件.bashrc,这样每次打开新的终端都会执行上面的代码vim ~/home/.bashrc# 在打开的文件最后写入 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/so# 保存退出
    
  5. 再次运行app

    $ ./app24$ ldd app$ ldd ./app                           # 查看app的依赖        linux-vdso.so.1 (0x00007fff4c1b5000)        libtools.so => /home/so/libtools.so (0x00007f470e7fd000)        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f470e40c000)        /lib64/ld-linux-x86-64.so.2 (0x00007f470ec01000)
    

4、原理

  • 静态库:GCC进行链接时,将静态库中的代码打包到可执行程序中

  • 动态库:GCC进行链接时,动态库的代码不会被打包到可执行程序中,只包含依赖

  • 程序启动之后,动态库会被动态加载到内存中,通过ldd(list dynamic dependencies)命令检查动态库依赖关系。

  • 如何定位共享库文件呢?

    当系统加载可执行程序时,能够指导其所依赖的库的名字,但是还需要知道绝对路径,此时需要系统的动态载入器来获取动态库的绝对路径。

    对于elf格式的可执行程序,有ld-linux.so来完成,它先后搜索DT_RPATH段,环境变量LD_LIBRARY_PATH,/etc/ld.so.cache文件列表,/lib/,/usr/lib目录找到库文件后将其载入内存。

5、区别

截屏2021-05-25 下午4.04.43

5.1 静态库

截屏2021-05-25 下午4.05.23
优点
  • 静态库被打包到应用程序中加载速度快
  • 发布程序无需提供静态库,移植方便
缺点
  • 当多个程序需要使用用同一个库文件运行时,需要同时加载多个库文件,消耗系统资源,浪费内存。如下图所示:

    截屏2021-05-25 下午4.09.42
  • 更新,部署,发布麻烦

5.2 动态库

截屏2021-05-25 下午4.13.16
优点
  • 可以实现进程间资源共享(共享库)

    截屏2021-05-25 下午4.15.58
  • 更新,部署,发布简单

  • 可以控制何时加载动态库

缺点

加载速度比静态库慢

发布程序时,需要提供依赖的动态库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值