一、静态库与共享库
1、静态库
静态库是一系列目标文件(.o)的集合,以.a结尾;
在程序链接时使用,链接命令会将程序中使用的函数代码从库文件中拷贝到应用程序中去;一旦链接完成,在执行程序时就不需要静态库了。由于使用静态库的程序都需要拷贝所使用函数的代码,生成a.out会比较大。
1.1 静态库的创建
a)编辑源程序 .c .h
b)编译生成目标文件 .o
c)打包成静态库文件
例:$ ar -r libmath.a calc.o show.o
ar [参数] 静态库文件名称 目标文件列表
-r:将目标文件插入到静态库,已存在则更新;
-t:列出静态库中的目标文件
注:提供静态库的同时也需要提供头文件;
1.2 静态库的调用方法
a)直接法
例:$ gcc main.c libmath.a
b)环境变量法
LIBRARY_PATH:指定搜索库的路径
例:$ export LIBRARY_PATH=$LIBRARY_PATH:.
$ cd static
$ gcc main.c -lmath
c)参数法(重点)
例:$ gcc main.c -lmath -L./
2、共享库
使用链接时并没有像静态库那样拷贝调用函数的代码,只是做了标记。程序开始运行时,该程序使用的动态库会被操作系统自动的加载到内存,供程序调用使用。
2.1 共享库的制作
1)编辑 .c .h文件
2)编译生成目标文件
例:$ gcc -c -fpic calc.c -o calc.o
-fpic:生成位置无关码
3)生成共享库文件
例:$ gcc -shared calc.o show.o -o libmath.so
-shared:生成共享代码
其中2)、3)可以合并成:
$ gcc -shared -fpic calc.c show.c -o libmath.so
产出:.so .h
2.2 共享库的使用
$ gcc main.c -Idyn -lmath -Ldyn
(dyn是文件夹的名字)
2.3 a.out的执行
LIBRARY_PATH:链接阶段
LD_LIBRARY_PATH:指定加载库的搜索路径(在程序加载运行阶段有效)
例:$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
2.4 静态库和共享库的对比分析
1)使用共享库比使用静态库编译生成a.out要小;
2)如果库中 .c 文件修改了(show.c)
- 如果使用的是共享库a.out不需要更新
- 反之,使用的静态库a.out需要更新
3)对于共享库而言,库中的代码只需要在内存中有一份,而使用静态库编译的程序,静态库中的某个函数对应的代码可能在内存中有多份;
4)部署稍显复杂
- 对于动态库:部署a.out xxx.so
LD_LIBRARY_PATH
- 对于静态库:部署a.out
2.5 自主加载共享库文件(了解)
#include <dlfcn.h>
void * dlopen(char *filename, flags)
-
功能:
- 加载共享库到内存; 参数:
-
第一个参数:自主加载的库文件名称(包含路径)
第二个参数:
RTLD_LAZY - - - - 使用时加载
RTLD_NOW - - - - 马上加载
#include <dlfcn.h>
int dlclose(void *handle);
-
功能:
- 卸载共享库;
#include <dlfcn.h>
void *dlsym(void *handle, const char *symbol);
-
功能:
- 主要用来查找共享库中某个函数在内存中的地址 返回值:
- success —- 指定函数所在的地址,error —- NULL;