从源码到可执行程序,经历预处理编译汇编链接四个阶段,其中编译就是将源文件生成中间文件
的过程,经过汇编后生成的未链接的.o文件也叫目标文件(object)
库文件就是将这些中间 .o 文件打包生成的文件,这个对一些共用函数,工具类函数打包复用是非常方便
省去调用编译的过程。
静态库:
1. 静态库对函数库的链接是在编译时期完成的
2. 程序在运行时与函数库再无瓜葛,移植方便
3. 浪费空间和资源,因为所有相关的目标文件都与牵连的函数库被链接成一个可执行文件
4. 静态库对程序的更新部署和发布都带来麻烦。
这样造成程序臃肿,可能会拷贝存在多分第三方库拷贝占用内存,所以就有了动态库
链接是不会将第三方库糅合进可执行文件中,占用内存变小,而且多个程序链接也只会有
一份拷贝。
动态库
1. 动态库把对一些函数的链接载入推迟到程序运行的时期
2. 可以实现进程间的资源共享
3. 将一些程序升级变得简单
4. 做到链接载入完全由程序员在程序代码中控制
动态库和静态库
- gcc默认链接方式:动态链接 ---动态库 .so文件
- 动态库:程序运行时才去链接动态库的代码,多个程序可以共享使用库的代码
- 静态链接需要加上 -static ---静态库 .a文件
- 静态库:编译时把代码链接到可执行文件中。程序运行的时候将不再需要静态库
- 原则上都是将所写的文件打包成一个文件供别人使用
如何生成自己的动态库和静态库
- 程序编译过程:预处理---编译---汇编---链接
- 生成一个库其实就是将所有的代码打包起来,最终得到一个库文件
- 生成动态库:gcc、g++
- 生成静态库:ar
- 需要先将源码文件编译成自己的目标文件(动态库可以gcc直接从源码生成),也就是从c ---.o
- 最终这些.o文件链接在一起生成动态库还是静态库或者可执行文件,取决于链接过程!
- 如果要生成的是一个库文件,那么这些代码中不能有main函数
如果要生成的是一个可执行程序,那么这些代码中有切只能有一个main函数 - 静态库:将所有的.o文件打包到一起生成
- 生成命令:ar -cr lib文件名.a 文件名.a(-c 创建 -r 模块替换)
- 动态库生成:--share是生成动态库的gcc链接选项,没有这个将认为生成可执行程序将所有.o文件打包
- 生成命令: gcc -share 文件名.o -o lib文件名.so
- 要生成一个动态库,gcc编译器告诉我们,在编译阶段,将一个.c--- .o需要加上一个编译选项
-fPIC:产生位置无关代码
使用 -fPIC 选项,会生成 PIC 代码。.so 要求为 PIC,以达到动态链接的目的,否则,无法实现动态链接
(动态库映射到虚拟地址空间时对应的位置是不确定的,因此不能生成绝对路径的地址) - 动态库是一个运行时库,需要在程序运行时也加载到内存中,并这个加载的过程是操作系统干的,回去指定位置加载动态库,因为我们需要将动态库放到指定的位置才可以运行程序
总结
静态库的创建:
- g++ -c test.cpp 生成.o文件
- ar -rc libtest.a test.o 生成.a文件
静态库的链接:
g++ test.cpp test -L -ltest -o
动态库的创建:
- g++ -shared -fPIC test.cpp -o libtest.so 生成.so文件
动态库的链接:
- g++ main.cpp -L. -ltest -o mian.out // main.cpp中链接使用libtest.so
- main.out LD_LIBRARY_PATH=. ./main.out // 添加路径并运行