Appearance
库
- 库是二进制的可执行文件,与二进制程序比较,库是不能单独运行的。
- 库需要被载入到内存中使用
- 标准的基础库中存放了很多已经写好的,成熟的,可以复用的功能代码,比如 printf...
- 不同操作系统有自己的库,不兼容
库分为静态库和动态库两种:
Winodws:静态库(*.lb),动态库(*.dll)
Linux:静态库(lib*.a),动态库(lib*.so)
Linux 库的位置:/lib & /usr/lib
查看程序依赖的动态库:
bash
ldd a.out静态库
通过静态库封装的功能函数,在程序编译到链接库步骤的时候,会将函数继承到可执行程序中。
优点:
- 程序运行的时候,与静态库没有任何关系,方便移植
缺点:
- 存储的时候浪费磁盘空间,运行的时候浪费内存空间
- 程序的更新部署比较麻烦
构建一个静态库
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:重置静态库索引
制作的步骤:
- 分文件,将功能函数与主函数分离:func.c <--> main.c
- 写头文件:func.h
- 根据上述静态库制作指令,将 func.c 放入静态库中
- a. 静态库的命名规则:
libxxx.a,其中xxx才是库的名字
- a. 静态库的命名规则:
- 根据下述指令链接静态库(静态库的使用)
使用静态库
bash
gcc main.c -L库的路径 -l库的名字
gcc main.c -o main -L库的路径 -l库的名称
gcc 01_sqlite3.c -L./ -lfunc -lsqlite3动态库(共享库)
将函数封装成动态库,函数的链接会推迟到函数运行的时候。
当程序指向到库函数的时候,会到内存中找相关的库函数:
- 若内存中不存在该动态函数库,则会将动态库函数加载到内存中
- 若内存中存在该动态函数库,则直接调用
优点:
- 存储的时候节省磁盘空间,运行的时候节省内存空间
- 程序更新部署比较方便,不需要重新编译和烧录
缺点:
- 程序运行的时候,如果没有遭到该动态函数库,会导致程序崩溃
- 运行的速率比静态库慢
动态库的制作
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:生成与加载位置无关的二进制文件
动态库制作流程:
- 分文件:main.c func.h func.h
- 联合编译,测试分文件是否成功:gcc main.c func.c
- 用上述动态库制作指令,将 func.c 制作成动态库
- 动态库的命名格式是
libxxx.so,xxx才是动态库的名字
- 动态库的命名格式是
- 动态库的使用如下
动态库的使用
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 需要加载配置文件
方法三(推荐)
编写环境变量配置文档:
cd /etc/ld.so.conf.d/- 创建一个以 .conf 结尾的配置文件
sudo touch my.conf sudo vim my.conf将动态库所在的文件夹的绝对路径添加到my.conf中- 一行只能放一个动态库的绝对路径
- 保存后退出,执行
sudo ldconfig,刷新环境变量