Skip to content
On this page

静态库与动态库


标签:clang/basic  

  1. 库是二进制的可执行文件,与二进制程序比较,库是不能单独运行的
  2. 库需要被载入到内存中使用
  3. 标准的基础库中存放了很多已经写好的,成熟的,可以复用的功能代码,比如 printf...
  4. 不同操作系统有自己的库,不兼容

库分为静态库和动态库两种:

Winodws:静态库(*.lb),动态库(*.dll)

Linux:静态库(lib*.a),动态库(lib*.so)

Linux 库的位置:/lib & /usr/lib

查看程序依赖的动态库:

bash
ldd a.out

静态库

通过静态库封装的功能函数,在程序编译到链接库步骤的时候,会将函数继承到可执行程序中。

优点:

  1. 程序运行的时候,与静态库没有任何关系,方便移植

缺点:

  1. 存储的时候浪费磁盘空间,运行的时候浪费内存空间
  2. 程序的更新部署比较麻烦

构建一个静态库

bash
gcc -c func.c -o func.o # 完成预处理,编译,汇编
ar -crs libfunc.a fun.o  # 生成一个静态库, func才是静态库的名字

ar -crs libfunc.a func1.o func2.o func3.o # 多个 .o 文件放到一个库里面
  • ar:创建,操作静态库的指令
  • -c:create 创建
  • -r:将文件放入静态库或者替换静态库中重名的文件
  • -s:重置静态库索引

制作的步骤:

  1. 分文件,将功能函数与主函数分离:func.c <--> main.c
  2. 写头文件:func.h
  3. 根据上述静态库制作指令,将 func.c 放入静态库中
    • a. 静态库的命名规则:libxxx.a,其中xxx才是库的名字
  4. 根据下述指令链接静态库(静态库的使用)

使用静态库

bash
gcc main.c -L库的路径 -l库的名字
gcc main.c -o main -L库的路径 -l库的名称

gcc 01_sqlite3.c -L./ -lfunc -lsqlite3

动态库(共享库)

将函数封装成动态库,函数的链接会推迟到函数运行的时候。

当程序指向到库函数的时候,会到内存中找相关的库函数:

  1. 若内存中不存在该动态函数库,则会将动态库函数加载到内存中
  2. 若内存中存在该动态函数库,则直接调用

优点:

  1. 存储的时候节省磁盘空间,运行的时候节省内存空间
  2. 程序更新部署比较方便,不需要重新编译和烧录

缺点:

  1. 程序运行的时候,如果没有遭到该动态函数库,会导致程序崩溃
  2. 运行的速率比静态库慢

动态库的制作

c
gcc -fPIC -c func.c -o func.o    # 完成预处理,编译,汇编
gcc -shared -o libmyfunc.so func.o # 生成一个动态库,动态库的名字:myfunc

gcc -shared -o libfunc.so func1.o func2.o

-fPIC:生成与加载位置无关的二进制文件

动态库制作流程:

  1. 分文件:main.c func.h func.h
  2. 联合编译,测试分文件是否成功:gcc main.c func.c
  3. 用上述动态库制作指令,将 func.c 制作成动态库
    • 动态库的命名格式是 libxxx.soxxx 才是动态库的名字
  4. 动态库的使用如下

动态库的使用

bash
gcc main.c -L库的路径 -l库的名字    # 生成 a.out
gcc main.c -o main -L库的路径 -l库的名字 # 生成 main

如果没有经过配置,系统默认会到 /lib/ 或者 /usr/lib 找动态库

动态库环境变量配置

方法一

移动动态库到 /lib/ 或者 /usr/lib/

例如:sudo mv libxxx.so /lib

次方法不安全,若覆盖系统库将导致系统崩溃

方法二

设置LD_LIBRARY_PATH环境变量:

bash
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库的绝对路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/mydir/10_lib/

该方法只能在 shell 临时有效,或者 shell 需要加载配置文件

方法三(推荐)

编写环境变量配置文档:

  1. cd /etc/ld.so.conf.d/
  2. 创建一个以 .conf 结尾的配置文件 sudo touch my.conf
  3. sudo vim my.conf将动态库所在的文件夹的绝对路径添加到 my.conf
    • 一行只能放一个动态库的绝对路径
  4. 保存后退出,执行sudo ldconfig,刷新环境变量

Last updated: