目录
系列文章目录
本系列博客重点在深圳大学计算机系统(2)课程的核心内容梳理,参考书目《深入理解计算机系统》(有问题欢迎在评论区讨论指出,或直接私信联系我)。
第一章 深入理解计算机系统01——计算机系统漫游_@李忆如的博客-CSDN博客
第二章 深入理解计算机系统02——信息的表示与处理_@李忆如的博客-CSDN博客
第三章 深入理解计算机系统03——程序的机器级表示_@李忆如的博客-CSDN博客
第四章 深入理解计算机系统04——存储_@李忆如的博客-CSDN博客
第五章 深入理解计算机系统05——链接
梗概
本篇博客主要介绍深入计算机系统书目第七章链接的相关知识。
一、理解链接与驱动
链接:将各种代码与数据片段收集并组合成为一个单一文件的过程,这个文件可被加载(复制)到内存并执行。可执行于编译、加载、运行时。
1.编译器驱动程序
编译及执行程序过程如下:
2.链接
以如下程序介绍链接:
链接任务:
0)隐含任务——节在内存空间的布局
1)符号解析(symbol resolution):建立符号引用和定义之间的联系
2)重定位(relocation):为每一个引用确定地址
3.ELF目标文件
链接常见的三种目标文件如图所示:
Tips:通用名称:ELF二进制文件
4.可重定位目标文件
经典的ELF可重定位目标文件结构如下:
经典ELF可执行目标文件结构如下(多程序头表、.init节、少两.rel):
二、符号与符号表
每个可重定位目标模块m都有一个符号表,它包含m定义与引用的符号信息,有以下三种链接符号。
1.符号相关定义
以如下一个C语言程序做示例:
Tips:注意区分存储属性和作用域——全局变量、静态全局变量、静态局部变量、局部变量。
堆上存储(全局变量、静态局部变量、静态全局变量)
栈上存储(局部变量)
全局作用(全局变量)
局部作用(静态全局变量、静态局部变量、局部变量)
2.符号表示例
符号表示例如图所示:
Tips:data为已初始化,bss为未初始化的静态变量,text为只定义(eg.函数名)。
3.符号解析
链接器解析多重定义的全局符号规则如下:
一些连接错误示例如下:
如何避免如上问题:
三、与库的链接
预处理
所有的注释用空格代替;
删除所有的#define, 展开所有的宏定义;
处理条件编译指令#if, #ifdef, #elif, #else, #endif
展开#include 包含的文件
保留编译器需要使用的#pragma指令
1.静态库及其符号解析
静态库使用案例与分析如下:
2.链接器使用静态库来解析引用过程
有以下自定义静态库
数据结构:维护三个动态变化的集合E、U和D
E:可重定位目标文件集合,被引用的目标文件将被拷贝到可执行文件中;
U:随着链接的展开而发现的未解析的符号集合,成功链接后最终该集合为空;
D:所有输入文件中已解析的符号集合(无论强弱);
算法要点:
1)初始化E/U/D为空;
2)逐个扫描命令行给出的文件f;
a)f是目标文件: E = E U {f},D = D U {f中的已定义符号},
重定位表项对应的符号与D进行匹配,未匹配的加入到U;
b)f是静态库,将U中的符号与f定义的符号相匹配,存在匹配模块m上的符号,E = E U {m},否则丢弃该库。
3)扫描结束
U非空:链接失败,将U未能解析的符号输出给用户。
U为空,链接成功,布局E中模块拼接成可执行文件,完成符号解 释和重定位
Tips:库的出现顺序很重要。
具体解析过程示例如下:
解析结果:
E中有main.o、myproc1.o及其调用的模块
D中有main、myproc1及其引用的符号
Tips:被链接模块应按调用顺序指定!
链接顺序问题示例如下:
3.动态库
静态库的不足
库函数被复制到每个运行进程的代码段,对于并发运行上百个进程的系统,造成内存空间的极大浪费
库函数被合并到可执行目标文件中,磁盘上存放着数千个可执行文件,造成磁盘空间的极大浪费
程序员需关注是否有函数库的新版本出现,并须定期下载、重新编译和链接,使用不便且编译耗时
动态链接共享库(shared library,又称共享库或动态链接库)
目标文件,包含有代码和数据
从程序中分离出来,磁盘和内存中都只有一个备份
可在装入时或运行时被动态加载并链接
Window称其为动态链接库(Dynamic Link Libraries,.dll文件)
Linux称其为动态共享对象( Dynamic Shared Objects, .so文件)
构建动态库示例如下:
基本链接过程总结如下图:
总结
以上便是深入理解计算机系统第七章——链接的核心知识。