CSAPP-链接
主要任务:
1.符号解析
在声明变量和函数之后,所有的符号声明都被保存到符号表。
而符号解析阶段会给每个符号一个定义。
2.重定位:
把每个符号的定义与一个内存位置关联起来,然后修改所有对这些符号的引用,让他们
指向内存位置。
符号解析:
会将符号引用和可重定位目标文件的符号表中的确定符号定义关联起来。
对于相同模块的局部符号(static属性),可以简单解决。
对于全局符号的引用,如果不是在当前模块定义的,会假设在其它模块中,然后通过链接器去查找,找不到则报错。
重载函数:
对于重载函数,会将每个函数和参数列表组合成一个对链接器来说唯一的名字。
多重定义的全局符号:
函数和已初始化的全局符号是强符号,未初始化的全局变量是弱符号。
如果有一个强和多个弱,那么选择强符号;若是多个弱符号,则随机选一个;不允许多个强符号。
/*foo1.c*/
int x = 15151;
int main
{}
/*foo2.c*/
int x = 15151;
void f(){}
如上面的代码会报错,x被多次定义。
/*foo1.c*/
int x = 15151;
int y = 111;
void f();
int main
{}
/*foo2.c*/
double x ;
void f()
{
x = 0.0;
}
double是8字节,int是4字节。因为强弱符号的关系,x=0.0中的x是foo的,于是双精度浮点会覆盖掉x,y的位置。
静态库:
相关的函数会被编译成独立的目标模块,然后封装成一个独立的静态库文件。
在链接的时候,连接器只会复制被程序引用的目标模块,以减小可执行文件的大小。
--
如何解析静态库:
链接器在根据命令行中输入的可重定位目标文件和静态库的顺序从左到右的扫描这些文件。然后维护三个集合:
E:会被合并的文件
U:未解析的符号集合
D:已经定义的文件集合
根据命令行的输入,判断f是目标文件还是存档文件
- 目标文件:链接器会把f加入E,然后修改U,D。
- 存档文件:在U中进行匹配,如果匹配到了,将存档文件成员 添加到E,然后修改UD。
--
如果不使用静态库:
1.将所有标程放到一个目标模块中
但是这样会导致每个可执行文件都包含所有的函数副本,浪费空间。而且任何函数被修改了,都要
重新编译库整个源文件。
2.将所有标程放到一个目录下
可以解决空间浪费的问题,但是这样需要我们显示地链接合适的目标模块,如果函数过多,容易出现错误,而且
浪费时间。
重定位:
1.重定位会将所有同一类型的合并为聚合节。然后将运行时地址赋予它们

2.修改代码节和数据节中对每个符号的引用,使它们指向正确的地址(相对引用 or 绝对引用重定位 等等)。
共享库:
静态库也有一定缺陷,需要定期维护更新。
几乎每个C都会使用IO,那么printf和scanf会被复制到每个运行进程的文本。那么在一个运行了上百个进程的系统上,无疑是一种浪费。
共享库不是像静态库那样将代码和数据嵌入到执行文件中,而是在内存中有一个共享库的.text节的副本,可以被不同的正在运行
的进程共享。
--
在共享库下,创建一个可执行程序:
会先静态执行一些链接,然后在程序加载的时候,动态地完成链接过程。
在加载运行的时候,会主要到.interp节(有动态链接器的路径)。然后加载这个动态链接器
- 重定位共享库的数据文本到某个内存段
- 重定位执行文件中所有对由 共享库定义的符号的引用也可以通过dlopen在应用程序中加载和链接共享库
参考资料:
不周山之读薄CSAPP
《深入理解计算机系统 》
多个进程间共享动态链接库原理
CSAPP-链接的更多相关文章
- 链接器(linker)的作用——CSAPP第7章读书笔记
首先说说我为什么要去读这一章.这个学期开OS的课,在Morden Operating System上读到和Process有关的内容时看到这样一句话:“Process is fundamentally ...
- CSAPP CH7链接的应用:静动态库制作与神奇的库打桩机制
目录 创建静态库 创建动态库 库打桩机制 编译时打桩: 链接时打桩 运行时打桩 运行时打桩的printf与malloc循环调用debug 使用LD_PRELOAD对任意可执行程序调用运行时打桩 总结 ...
- 【CSAPP笔记】13. 链接
下面就要进入本书的第二部分--在系统上运行程序.书的第一部分,主要是研究单个应用程序,关注的是数据类型.机器指令.程序性能.存储器系统等话题.在书的第二部分,我们继续对计算机系统的探索.现代操作系统与 ...
- CSAPP阅读笔记-链接-第七章-P464-P500
链接概述 经预处理器->编译器->汇编器处理后,源文件可被转化为一组可重定位目标文件,链接器将它们组合起来形成可执行文件. 每个可重定位目标文件由不同的“代码节”和“数据节”组成,每一个节 ...
- 菜鸟在C语言编译,链接时可能遇到的两个问题
最近在看 CSAPP (Computer Systems A Programmers Perspective 2nd) 的第七章 链接.学到了点东西,跟大家分享.下文中的例子都是出自CSAPP第七章. ...
- 在Ubuntu下使用 csapp.h 和 csapp.c
它山之石可以攻玉. 对于<深入理解计算机系统>这本神人写就的神书, 我等凡人就不评论什么啦. 这本书的 第二,三 部分, 真的真的对我理解操作系统有很大的帮助. (当然, 如果你不看第一部 ...
- CSAPP读书随笔之一:为什么汇编器会将call指令中的引用的初始值设置为-4
CSAPP,即<深入理解计算机系统:程序员视角>第三版,是一本好书,但读起来确需要具备相当的基本功.而且,有的表述(中译文)还不太直白. 比如,第463页提到,(对于32位系统)为什么汇编 ...
- [CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口
1 平台 转http://blog.csdn.net/misskissc/article/details/43063419 1.1 硬件 Table 1. 硬件(lscpu) Architecture ...
- [CSAPP笔记][第九章虚拟存储器][吐血1500行]
9.虚拟存储器 为了更加有效地管理存储器且少出错,现代系统提供了对主存的抽象概念,叫做虚拟存储器(VM). 虚拟存储器是硬件异常,硬件地址翻译,主存,磁盘文件和内核软件的完美交互. 为每个进程提供一个 ...
- [CSAPP笔记][第十一章网络编程]
第十一章 网络编程 我们需要理解基本的客户端-服务端编程模型,以及如何编写使用因特网提供的服务的客户端-服务端程序. 最后,我们将把所有这些概念结合起来,开发一个小的但功能齐全的Web服务器,能够为真 ...
随机推荐
- .net mvc 利用分部视图局部刷新.
页面利于$.Ajax: $(function(){ $("#btnpartview").click(function () { var model = []; model.push ...
- sublime的使用技巧
ctr+shift+d是复制当前行当下一行2.使用Sublime text 3 编写代码是一种享受,使用Sublime text 3 格式化HTML代码,需要安装插件,具体安装步骤如下:1.打开菜单- ...
- web api 如何通过接收文件流的方式,接收客户端及前端上传的文件
服务端接收文件流代码: public async Task<HttpResponseMessage> ReceiveFileByStream() { var stream = HttpCo ...
- Ansible自动化运维工具-上
[Ansible特点] 1)Ansible与saltstack均是基于Python语言开发的 2)安装使用简单,基于不同插件和模块实现各种软件,平台,版本的管理以及支持虚拟容器多层级的部署 3)不需要 ...
- 新概念英语(1-29)Come in, Amy.
How must Amy clean the floor? A:Come in, Amy. Shut the door, please. This bedroom's very untidy. B:W ...
- IntelliJ IDEA开发Scala代码,与java集成,maven打包编译
今天尝试了一下在IntelliJ IDEA里面写Scala代码,并且做到和Java代码相互调用,折腾了一下把过程记录下来. 首先需要给IntelliJ IDEA安装一下Scala的插件,在IDEA的启 ...
- Django 相关
Web框架本质 其实所有的Web应用本质就是一个socket服务端,而用户的浏览器就是一个socket客户端.简单的socket代码如下: import socket sk = socket.sock ...
- 写给 Android 应用工程师的 Binder 原理剖析
写给 Android 应用工程师的 Binder 原理剖析 一. 前言 这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔.生怕自己理解上还有偏差,对大家造成误解,贻笑大方.又怕自己理 ...
- [CodeForces10D]LCIS(最长公共上升子序列) - DP
Description 给定两个数列,求最长公共上升子序列,并输出其中一种方案. Input&Output Input 第一行一个整数n(0<n<=500),数列a的长度. 第二行 ...
- c语言一个显示星号的函数(隐藏密码)
显示星号 void star(char p[]) //显示星号 { int j; while((p[j] = getch())!='\r') { if(p[j] !='\b') { pr ...