静态库和动态库
1. 自作静态链接库使用
**制作流程:**
- 编写xx.c和xx.h文件
xx.h中声明函数原型
xx.c中定义函数 - 本例通过添加Makefile文件通过make生成.a库文件
- Makefile文件编写:
all:
gcc 1.static_lib.c -o 1.static_lib.o -c //-c 参数只编译不连接
ar -rc libstatic.a 1.static_lib.o //ar 命令生成库文件 .a库文件
make:
生成xx.a库文件
nm:linux中测试xxx.a文件里有都有哪些函数
nm libstatic.a
staticlib.o:
00000014 T add
00000000 T fun1
U puts
发布库的方法是:把库xx.a和xx.h放到引用的你工程目录下即可
引用库只需要添加对于的头文件
引用库文件,编译链接命令:
==gcc testlib.c -o -lstatic -L. ==
-lstatic :static就是库名称
-L. :设置库文件的路径,如果没有指定-L.(注意有点,点代表当前目录)
常见错误:
gcc test.c -o test
//在链接阶段出现报错。
/tmp/ccvJNYNm.o: In function `main':
test.c:(.text+0xa): undefined reference to `fun1'
test.c:(.text+0x1e): undefined reference to `add'
没有指定库名称,系统默认只给的常用的几个库名,大多数库在引用是属于给定如:数学库需要加-lm
gcc test.c -o test -lstatic
//指示找不到库文件,需要加-L.参数指定库路径:
/usr/bin/ld: cannot find -lstatic
collect2: error: ld returned 1 exit status
最后编译链接:gcc test.c -o test -lstatic -L. //编译链接引用到的第三方库.C文件
2、动态链接库(后缀.so)
与windous的.dll是一样意思
创建动态链接库:
步骤一:同静态链接库创建XXX.C和XXX.h 文件,.C用来存放函数定义,.h文件用来存放对于XXX.c文件中函数定义的声明,作为发布文件之一。
创建编译文件Makefile文件:
gcc static_lib.c -o aston.o -c -fPIC
gcc -o libaston.so aston.o -shared //生成.os动态链接库。
解析:
-fPIC:添加此条件编译为位置无关吗,消除位置有关的限制。
-shared:共享库 意为共享形式的目标文件
步骤二:使用共享库,发布给使用方只发:xxx.h 和xxx.so
linux中编译命令:
gcc testlib.c -o -laston -L. //如果动态链接库和静态链接库都有,默认动态链接库
-laston 指定动态链接库名
-L. 指定动态链接库路径(.代表当前目录)
注意:编译后能正常生成可执行文件,引用了动态库的程序运行时,报错,提示找不到必须要加载动态链接库的(运行时程序环境中,程序运行时发现有引用动态链接库,链接器就去指定的路径(一般系统固定/usr/lib)去找相应的动态链接库.so文件,如果没有找到会报错)
./test: error while loading shared libraries: libdytest.so: cannot open shared object file: No such file or directory
解决方法一:把库文件放到:/usr/lib即可(系统的共享库)这样可以解决问题,一般不会这样做。
解决方案二:通过导出环境变量的方法,将.so所在的目录导出到LD_LIBRARY_PATH环境变量中即可解决
export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/存放动态库文件的目录
导出后查看:
echo $LD_LIBRARY_PATH
解决方法三:ubuntu下:ldconfig ,兼容性不好不推荐使用,只能在ubuntu中使用,但如果使用过多库函数,也会拖累系统性能。在linux中此方法不适用。
常用命令:
ldd +程序名
linux-gate.so.1 => (0xb7760000)
libdytest.so (0xb775a000) 测试用到的自建动态库
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7597000)
/lib/ld-linux.so.2 (0xb7761000)
命令作用:
可以在一个使用了共享库的程序执行之前解析出这个程序使用了那些共享库,并且查看这些库能否被加载。
静态库和动态库区别:
通过都可以实现需求,不同是调用静态库在链接阶段,如某个地方引用了静态库连接器原封不动复制一份到库代码到可执行文件中。多个引用就会有多个副本。当库文件发生更新时,所有使用他的程序都要重新编译、链接、发布。
使用动态库时,如果某个函数引用了动态链接库,编译链接时只会打上标注并不是复制。带程序运行时,如果暂时没有调用动态链接库的函数,并不会被加载到内存中。只有调用前才被加载到内存上提供调用,多次引用此动态库函数内存中只加载一份。