动态库和静态库

动态链接库、静态链接库。

库的命名规则

Linux 下,以 lib 开头,.a结尾是静态库,.so结尾是动态库。

Windows 下,以 lib 开头,.lib是静态库,.dll是动态库。

静态库

Windows 下 的后缀是 .lib,Linux 下的后缀是 .a。

把一些 .o 文件打包到一起生成了一种特殊的二进制程序,自身不能直接执行,但是可以和其他的 .c/.cpp 文件一起编译生成一个新的可执行程序,这个新的可执行程序就可以单独发布出去了。

应用场景:发布小型程序的时候,就可以使用静态库的方式编译生成一个单独的可执行程序,并且不依赖其他的库,发布比较方便。

栗子 mymath.a

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// add.h
#pragma once
int add(int a, int b);

// add.c
#include "add.h"
int add(int a, int b) {
return a + b;
}

// sub.h
#pragma once
int sub(int, int);

// sub.c
#include "sub.h"
int sub(int a, int b) {
return a - b;
}

// main.c
#include <stdio.h>
#include "sub.h"
#include "add.h"

int main(void) {
int a = 10, b = 10;
printf("add(20, 10) = %d\n", add(a, b));
printf("sub(20, 10) = %d\n", sub(a, b));
return 0;
}

生成静态库并使用

生成静态库

ar -rc libmymath.a add.o sub.o

ar 是 GNU 归档工具;rc 表示(replace and create)

查看静态库中的目录列表

ar -tv libmymath.a

t 列出静态库中的文件;v 详细信息(verbose)。

编译

gcc main.c -L. -lmymath

-L 指定库路径,在当前目录下;-l 指定库名。

动态库

把一些 .c/.cpp 文件编译成了一种特殊的二进制程序,自身不能直接执行,但是可以被其他可执行程序调用。在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)。

动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。

应用场景:客户端更新时不必要更新整个程序,而是只更新其中的一部分模块。其中的模块就是以动态链接库的方式组织的。

栗子 mymath.so

生成动态库并使用

生成动态库

gcc -fPIC -c sub.c add.c

-fPIC 产生位置无关码(position independent code)

gcc -shared -o libmymath.so *.o

-shared 表示生成共享库格式

使用动态库

gcc main.c -L. -lmymath

-L 指定路径;-l 指定动态库名称。

查看某个程序的动态库依赖

  • Linux 下ldd exeFileName

    ldd

  • Mac 下otool -L execFileName

    otool -L

运行动态库

有的时候可能找不到库,就需要配置下了。

  1. 拷贝.so文件到系统共享库路径下,一般指/usr/lib

  2. 更改 LIBRARY_PATH 环境变量

    1
    export LD_LIBRARY_PATH=.
  3. ldconfig 配置/etc/ld.so.conf.d/,ldconfig更新

库的搜索路径

  1. 从左到右搜索 -L 指定的目录。
  2. 由环境变量指定的目录(LIBRARY_PATH,设定这个环境变量来提醒系统去哪些目录找动态库)
  3. 由系统指定的目录(/usr/lib /usr/local/lib)

文章作者: ahoj
文章链接: https://ahoj.cc/2019/06/动态库和静态库/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ahoj 的小本本