库文件的制作与使用
什么是库文件:
-
库文件是计算机中的一类文件统称,提供给开发者一些开箱即用的变量、函数、类,是若干个目标文件的集合,这样可以既可以保护源码,同时也对源码的使用提供了方便管理、使用、安全性高
-
库文件分成静态库、动态库,区别具体在于程序的
静态库与动态库(共享库)的区别:
-
静态库在程序链接之前就已经复制到了程序中,一起形成一个可执行文件,后续链接和加载到内存就不需要静态库文件参与;动态库在链接之前没有复制,而是在程序运行时,一起由系统加载到内存中,当执行到动态库中的语句时,内存发生跳转到动态库的代码段执行,执行结束后跳转回程序的代码段往下执行;这是这两个文件的最本质的区别
静态库的制作与使用:
创建静态库:
# 编译出要打包的目标文件: gcc -c xxx1.c gcc -c xxx2.c ... # 把目标文件合并打包成静态库文件 # 静态库一定是 前缀lib + 库名xxx +后缀.a ar -r libxxx.a xxx1.o xxx2.o ... # ar 是一个专门控制静态库的命令集合 -r # 把目标文件合并成一个静态库文件,如果已有静态库则会更新 -q # 向静态库中添加目标文件 -t # 查看静态库中有哪些目标文件 -d # 从静态库中删除目标文件 -x # 把静态库展开成目标文件
使用静态库:
# 方法1 直接使用 相当于把库文件当做目标文件一样使用 意义不大 gcc main.c libxxx.a # 方法2,通过设置LIBRARY_PATH环境变量的值来指定库文件的查找路径 # 前提是需要将静态库放入自己指定的静态库查找路径中 # 1、打开Linux系统配置文件 vim ~/.bashrc # 2、在文件末尾追加内容 exprot LIBRARY_PATH=$LIBRARY_PATH:要指定的路径 # 3、保存退出后,重新加载配置文件 source ~/.bashrc 通过-l库名 指定要使用的库 gcc main.c -lxxx # 方法3:通过-l库名 指定使用当前工作路径下的库 gcc main.c -lxxx #注意:libxxx.a必须在当前路径下或者系统指定路径 # 方法4:通过-L路径 去该路径查找库,找不到继续从当前目录、系统指定目录找 gcc main.c -lxxx -Lpath 注意:如果要删除系统配置文件中的环境变量,需要重启系统,才会生效
动态库的制作与使用:
创建动态库文件:
# 编译出目标文件,-fpic 编译出与位置无关的代码 gcc -c -fpic xxx1.c gcc -c -fpic xxx2.c ... # 把目标文件打包合并成有执行权限的动态库文件libxxx.so gcc -shared xxx1.o xxx2.o ... -o libxxx.so
使用动态库:
# 方法1,直接调用 gcc main.c libxxx.so # 只要当前路径下有so就可以生成a.out a.out # 可能报错 默认下不会在当前路径加载so 只会去默认路径/lib # 方法2,通过设置LIBRARY_PATH环境变量的值来指定库文件的查找路径 # 前提是需要将静态库放入自己指定的静态库查找路径中 # 1、打开Linux系统配置文件 vim ~/.bashrc # 2、在文件末尾追加内容 exprot LIBRARY_PATH=$LIBRARY_PATH:要指定的路径 # 3、保存退出后,重新加载配置文件 source ~/.bashrc 通过-l库名 指定要使用的库 gcc main.c -lxxx # 方法3:通过-l库名 指定使用当前工作路径下的库 gcc main.c -lxxx #注意:libxxx.a必须在当前路径下或者系统指定路径 # 方法4:通过-L路径 去该路径查找库,找不到继续从当前目录、系统指定目录找 gcc main.c -lxxx -Lpath 注意:如果无法执行a.out, 需要检查系统能否在正确的路径下加载对应的动态库文件,检查LD_LIBRARY_PATH环境变量的值 注意:在指定路径中,存在同名的静态库(libxxx.a)和动态库文件(libxxx.so)时,系统默认优先使用动态库文件 可以通过参数 -static
静态库与动态库的优缺点对比
静态库优点:
使用方便:
-
在与静态库文件编译生成可执行文件后,编译器会把静态库中的内容一起编译到可执行文件中,在后续的执行程序时不需要依赖静态库文件了,并且可执行文件可以跨平台、跨设备直接运行
运行速度快:
-
因为静态库文件是拷贝到可执行文件中,所以程序运行时不发生内存跳转,运行速度比动态库更快
静态库缺点:
浪费内存:
-
假如有一个静态库libxxx.a,以及多个程序a.out b.out c.out都是用该静态库,那么libxxx.a的内容会分别给它们各拷贝一份,如果三个程序同时运行,静态库就会在内存中存在同样的三份,内存冗余,并且相比于动态库的可执行文件而言,静态库的可执行文件更大
更新麻烦:
-
如果静态库的内容发生了改变:版本更迭、修改BUG等,那么所有使用过该静态库的可执行文件都需要重新编译,会耗费大量时间。
动态库的优点:
节约内存:
-
所有使用同一个动态库的可执行文件,它们的动态库只会加载到内存一次,不同的程序可以使用那一次加载到内存的动态库内容,所以能够节约内存,这也是动态库也称为“共享库”的原因
更新方便:
-
当动态库的内容更新,但是函数名、参数格式、返回值这些没改动的前提下,只需要重新编译动态库文件即可,直接运行原来的可执行文件,系统会加载最新版的动态库文件,不需要全部重新编译,节约时间
总结:实际操作不会考,但是对比得知道
额外知识了解:动态加载动态库
作业:把常用的数据结构和算法封装动态库
使用库文件的辅助工具:
# 查看目标文件、可执行文件、静态库、共享库文件的符号列表 nm <filename> # 删除目标文件、可执行文件、静态库、共享库文件的符号列表、调试信息,有效降低文件大小 strip <filename> # 查看可执行文件依赖于哪些动态库 ldd <filename> # 把二进制转换成汇编,就是反汇编 objdump <参数选项> <filename>