- 链接作用是将各种数据和代码的部分打包。
- 链接可以运行在“编译时”、“加载时”、“运行时”,分别对应的编译机器代码(传统静态链接);加载时共享库动态链接(动态链接);运行时共享库动态链接(动态链接)
连接器的重要作用:分离编译;就是模块化。使得大型应用程序分为小型的模块,再最终连接起来。修改代码也不用重新编译,而是重新连接即可
理解链接可以帮助解决:
- 构造大型程序:解决“不兼容库版本”或者“缺少库”的问题
- 避免危险的编程错误
- 理解语言的作用域规则是如何是实现的
- 利用共享库:共享库和动态链接。大多数web服务器都依赖于共享库的动态链接来提供动态内容。
无论什么样的操作系统,基本链接的概念是相通的,细节可能不尽相同,但是概念和思想是相同的。
一个程序:cpp-->.i-->.s-->.o-->.exe
对应:预处理器-->编译器--》汇编器--》链接器 pre-->ccl-->as-->ld
链接器输入.o;输出ELF(Executable and Linkable Format)
静态链接:以一组可重定位目标文件和命令行参数作为输入,生成一个完全连接的可加载和运行的可执行目标文件作为输出。 secton;
目标文件:.o;.exe.so
- .o:可重定位二进制文件
- .exe:可执行目标文件:二进制
- .so(dll):共享目标文件:二进制(加载或运行时)
各个系统之间的目标文件各不相同;但是基本概念是类似的。
有趣的是,static属性的本地过程变量是不在栈中管理的。因此,可以利用static隐藏变量和函数名,类似private
lib+obj = exe ; lib+.o = elf
静态库链接:.lib:当.lib被静态调用的时候,程序只拷贝其中应用程序引用的目标模块。存储器总是稀缺资源
- 缺点;
所有的exe都包含一份相同的代码,并且会使得exe很大。
修改exe的时候必须重新编译.
- 优点:
省事,不存在dll hell的问题。
注意:不管是静态库还是动态库,他们都只用库中相应的模块。
加载:将程序(可执行目标文件)拷贝到存储器的过程。linux运行时存储器映像:
内核虚拟存储器(用户代码不可见) |
用户栈 |
共享库存储器映射区 |
堆区 |
数据区:读写段 |
数据区:只读段 |
未使用(0x08048000) |
动态链接共享库:在运行时,可以加载到任意的存储器地址;并和一个存储器中的程序连接起来。
特点:可以共享且内存里只有一个副本
微软的dll就是通过loadlibrary-->getprocaddress-->freelibrary来调用动态链接的。