动态库与静态库的区别
- 什么是库
库就是编译好的二进制代码加上头文件来供人们使用 - 什么时候会用到库
- 代码需要给别人使用,但是不希望释出源码,给出库文件及头文件
- 模块化编程对于一些几乎不会动的代码,编译成库文件,再次编译文件时只用链接即可,节省时间
静态库
什么是静态库
- 静态库之所以叫做静态,是因为在编译目标程序的时候静态库的代码直接被拷贝到目标程序代码中,这段代码在目标程序中是不会变动的
优缺点
- 静态库的好处是目标程序编译好后不会在依赖外部的静态库(因为静态库的代码已经被拷贝编译到目标程序中了),这样目标程序在运行过程中不会出现找不到库文件的错误
- 同时缺点也很明显,使用静态库会造成目标程序的体积很大
- 当升级了静态库的功能时,需要重新编译目标程序
动态库
什么是动态库
- 动态库在目标程序的编译中不会被整合到目标程序的代码段中, 目标程序指挥存储指向目标程序的引用.等程序运行时,需要动态库代码所提供的功能时才会动态加载该动态库去执行该功能
优缺点
- 由于动态库不会被拷贝到目标程序中,所以不会影响目标程序的体积
- 一个动态库可以被很多个目标程序所使用
- 动态库有功能升级时,如果函数接口不发生改变,那么目标程序不需要重新编译
- 由于动态库是动态加载的,所以目标程序执行的速度不如使用静态库时快
- 如果动态库却是,目标程序则无法运行
静态库的命名与制作方法
命名规则
lib + 库名 + .a
制作步骤
- 首先生成 .o 文件,
gcc -c src./*.c
mv *.o ofile
- 将生成的 .o 文件打包成静态库文件
ar rcs libMycal.a ofile/*.o
-r: 插入成员文件到索要制作的库中,如果存在同名文件则将原同名文件替换掉
-c:创造一个archive,这里就是建立库文件
-s:将文件成员索引写入该文档
发布和使用
发布需要发布头文件和静态库,即释出上图中的header.h和libMycal.c
使用时:
- 需要在程序中包含头文件, 在程序中调用头文件中声明的静态库函数即可
- 编译方法:
gcc main.c -Ihead libMycal.a -o myapp
或gcc main.c -Ihead -L ./ -l Mycal -o myapp
查看静态库
-
nm 静态库名:查看静态库的组成
nm libMycal.a
-
nm 二进制文件: 查看文件中有什么
nm myapp
-
引用静态库时最小的打包文件单位为.o文件,意思就是打包在最终发布的程序中的最小单位是.o文件
动态库的命名与制作方法
命名规则
lib + 库名 + .so
制作步骤
- 生成与位置无关的代码(即生成与位置无关的.o文件)
gcc -fPIC -c src/*.c -Ihead
mv *.o ofile
(由于最终目标程序使用动态库时是动态加载的,加载时放置在用户空间中的位置不定,所以需要生成与位置无关的代码) - 将.o文件打包成共享库(动态库)
gcc -shared -o libMyCal.so ofile/*.o
发布和使用
发布:发布时释出动态库libMycal.so和头文件header.h
使用动态库时编译方法:
1. gcc main.c ./libMyCal.so -Ihead -o myapp
2. 或者gcc main.c -L ./ -l MyCal -Ihead -o myapp
找不到库的解决方法
这里第二种方法编译出来的目标程序会提示找不到库
ldd mysum 可以查看函数的依赖库
这里可以看到libMyCal.so无法找到,上图中最后一行时动态链接器,动态连接器会从/lib寻找库文件
两种解决方法
- 设置环境变量
export LD_LIBRARY_PATH=./
- 配置动态链接库的配置文件ld.so.conf, 将路径写到里面
更新配置 ldconfig -v