首先说说我为什么要去读这一章。这个学期开OS的课,在Morden Operating System上读到和Process有关的内容时看到这样一句话:“Process is fundamentally a container that holds all the information needed to run a program.”当时瞬间就想到了之前在csapp上看的模棱两可的“目标可执行文件”这个概念,于是重新又把它的第7章给读了一遍。


  要理解linker的作用,首先要搞明白他在整个计算机系统中处于一个什么样的位置。

  关于一个程序是怎样从码农们手撕的代码变成内存中能跑起来的程序这个过程就不再过多的叙述,这篇文章只是着重的去讲一下有关linker的这一部分。我们可以看到,linker的接受的输入是若干个.o文件,简单的说就是经过汇编器编译后生成的机器码,学名叫“relocatable object file(可重定位的目标文件)”,概念相近的称呼也有“module(模块)”。而汇编器的输出,是一个名叫“executable object program(目标可执行文件)”的二进制文件,这个文件的特征就是可以直接拷贝到内存中不需做任何的更改便可以运行。那么我们研究linker的作用是什么就可以从这里入手——为了构造最终的目标可执行文件,他需要对输入若干可重定位的目标文件做哪些事情?

  linker的作用主要有两个:

  (1)符号解析(symbol resolution):将每个符号的定义和每个符号的引用联系起来。(就是让系统明白,当这个程序run的时候,遇到的具体的变量或函数名,他们到底来自哪个文件的定义?是自己这个?还是其他一起输入linker的文件?)

  (2)重定位(relocation):把每个符号定义与存储器中的一个具体位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器的位置,从而重定位这些节。(在取得了每个符号的引用和定义的连接之后,要把符号的定义在存储器中绑定一个具体的地址)

  书中对符号的解释不是太清楚,至少我一开始的时候没太理解这个概念,在这儿结合书本的内容我用自己的话来概括下我对这个概念的理解。“符号”可以分为3类:

  1、由该模块定义的并且能被其他模块引用的“全局符号”。这里的“全局符号”对应于C语言中的非静态的函数和全局变量。

  2、由其他模块定义的由该模块引用的“全局符号”。解释同上

  3、由该模块定义的并且不能被其他模块引用的“全局符号”。对应于C语言中的静态变量,即static变量。static关键字相当于C语言中的“private”,即只能被自己这个文件(模块)使用的全局变量

  应当注意的是这里的变量全是全局变量而不是函数内部的私有变量,私有变量由运行时stack存储管理,linker对她并不感兴趣:)


  那么在了解了符号的概念之后,要想具体的了解linker对可重定位的目标可执行文件做的一些事情,就要了解relocatable object file的一些结构(他是怎么记录自身的各种符号信息的?)对不对?

  大家第一次看到这个图不要害怕,其实这就是汇编器(Assembler)将编译器处理的源代码文件进行进一步的编译或者说汇编之后形成的可重定位的目标可执行文件。这个文件的一个个小格子就是一个个的“节(section)”,他们存放该program的各种信息,在这里我只会解释几个我认为对理解linker作用很有必要的section。

.text:已编译程序的机器代码。

.data:已初始化的全局C变量。

.bss:未初始化的全局C变量。在这里符号只是一个占位符,它不占用任何的内存空间。

.symtab:一个符号表,存放在程序中定义和引用的函数和全部全局变量的信息。

.rel.test:存放代码的重定位条目(relocation entry)。

.rel.data:存放数据的重定位条目。


  以上都属于本章的基础知识铺垫部分,理解了上述内容,就可以很容易的理解linker对可重定位的目标可执行文件所做的操作了。

1、符号解析

  linker解析符号的方法是将每个符号的引用与所有输入的relocatable object file中的.symtab节中所有的符号定义中确定的一个联系起来。

 1.1链接器如何解释多重定义的全局符号?

  对于定义和引用都在一个module中的符号,linker的操作很简单,不需要指来指去改来改去;而真正要深入探讨的操作是对定义和引用不在同一个文件中的符号,尤其是当寻找到的符号定义有重名时。对此linker的做法是:

  (1)定义强符号和弱符号的概念。函数和已初始化的变量是强符号,为初始化的变量是弱符号。

  (2)设定规则。当有多重定义冲突的时候,linker遵循的规则是:

    one:不允许有多个强符号定义

    two:如果有一个强符号和多个弱符号定义,那么选择强符号定义

    three:如果有多个弱符号定义,那么随便选择一个

 1.2与静态库链接

  为什么会有“静态库”(static libraries)这个概念?

  首先在C语言编程中,我们需要实现丰富的功能,就要使用各种各样的函数接口。以ANSI C为例,它定义了一组广泛的标准I/O、字符串操作和整数数学函数,例如atoi、printf、scanf、strcpy、rand。他们在libc.a库中,对每个C程序来说都是可用的。如果不使用静态库,我们看看编程开发人员可以用什么其他的办法来向用户提供这些函数。

  一种实现的方法是让编译器直接辨认出对函数的调用,并直接生成相应的代码——这显然是不可行的,C语言中有大量的函数,这样做显然会使得编译器的设计变得相当复杂,每次添加、修改、删除一个函数时,都需要一个新的编译器版本。虽然对于编程人员而言这样是十分方便的,因为所有的标准函数都是直接可用的。

  另一种实现的方法是将所有的这些函数放到一个单独的可重定位的目标可执行文件中,它的优点是将编译器的设计与标准函数的实现分离开来,在一定程度上仍然便利编程人员。但是这样做的缺点却是每次运行程序的时候都要将该装载函数的rof文件copy到内存中去,而这样是很浪费内存空间的。而且同样将这么一大批函数赛到一个文件中,每次的维护都要重现编译整个源文件,这又是相当大的一个工作量。

  何为静态库?

  在Unix中,静态库以archive这种特殊的文件格式存在于磁盘中,是一组连接起来的relocatable object file的集合。

  

 1.3链接器如何使用静态库来解析引用

  维护一个基于(U,E,D)三个集合的算法


2、重定位

  在这个过程中,将合并模块并为每个符号分配运行时的地址。重定位由两个步骤组成:

  在这里有一个需要理解的概念是重定位条目(relocation entry)。在汇编器生成一个可重定位的目标模块时,当遇到UNDEFINED的符号,即不知道该数据或代码最终该存放到存储器的什么位置时,它就会为该符号生成一个重定位条目,即之前介绍的可重定位目标文件中的.rel.text和.rel.data两个表所记录的内容。

链接器(linker)的作用——CSAPP第7章读书笔记的更多相关文章

  1. CSAPP 第三章 读书笔记

    程序的机器级表示 AT&T与Intel格式的汇编代码 我们的表述是ATT(根据"AT&T"命名的, AT&T是运营贝尔实验室多年的公 司)格式的汇编代码,这 ...

  2. 2013337朱荟潼 Linux&深入理解计算机系统第七章读书笔记——链接

    第七章--链接 0.总结 链接编译时可以采用静态链接或动态链接. 连接器主要任务:符号解析和重定位. 多个目标文件可定义相同的符号,可以被连接到一个单独的静态库. 链接器可以生成部分链接的可执行文件 ...

  3. CSAPP:第一章学习笔记:斗之气1段

    一.信息就是位+上下文:系统中的所有信息(包括磁盘文件.内存中的程序.网络上传送的数据),都是由一串比特表示,根据上下文对这些比特表示进行翻译. 二.C程序编译过程 1.源码结构 // test.c ...

  4. CSAPP:第二章学习笔记:斗之气2段

    一.字长:虚拟地址通过一个字来编码,字长为32位,则可以标识2^32个地址空间,每个空间为一个字节,故为4G 二.字节序:当解释多个字节类型时,存在大小端字节序问题 0x1234567,在大小端表示法 ...

  5. LLD-LLVM链接器

    LLD-LLVM链接器 LLD是LLVM项目中的链接器,是系统链接器的直接替代,并且运行速度比它们快得多.它还提供了对工具链开发人员有用的功能. 链接器按完整性降序支持ELF(Unix),PE / C ...

  6. OpenGL立方体在世界坐标系中_缩放_旋转_平移_顶点片源着色器_光照作用_棋盘纹理贴图

    读取bmp等图片格式中的像素还有难度,就先用这个棋盘图象素来弄了 代码打错一个就一直First-chance exception ,貌似还有一个要用q或者Q才能成功退出,不知道缺少哪句,我用窗口红叉退 ...

  7. C编译器、链接器、加载器详解

    摘自http://blog.csdn.net/zzxian/article/details/16820035 C编译器.链接器.加载器详解 一.概述 C语言的编译链接过程要把我们编写的一个c程序(源代 ...

  8. 深入探究VC —— 链接器link.exe(4)

    在程序编译完成后,生成的文件是以.obj为扩展名的对象文件,link.exe是将这些对象文件与库链接起来以创建可执行文件或动态链接库文件的工具. link.exe的输入文件包括obj文件.lib文件. ...

  9. C入门语言基础一[可移植性、涉及的三种文件、编程7个步骤、编译器、链接器]

    Review Questions What dose portability mean in the context of programming? 文中讲到的可移植性是什么意思?   C本身是不涉及 ...

随机推荐

  1. Android 模仿微信启动动画(转)

    本文内容 环境 项目结构 演示微信启动动画 本文演示微信启动动画.请点击此处下载,自行调试. 顺便抱怨一下,实践性(与研究性质的相对)技术博的“七宗罪”: 第一宗罪,错字连篇,逻辑不清: 第二宗罪,文 ...

  2. yii phpexcel <转>

    原文详情参见 这里 1.下载phpexcel,将压缩包中的classes复制到protected/extensions下并修改为PHPExcel. 2.修改YII配置文件config/main.php ...

  3. visual studio 2015 删除空行 ,缩进css

    查找  ^(?([^\r\n])\s)*\r?$\r?\n

  4. JNI测试-java调用c算法并返回java调用处-1到20阶乘的和

    一,java端: 定义native方法, 'public native long factorial(int n);', 该方法用c/c++实现,计算'1到20阶乘的和',参数中'int n'是前n项 ...

  5. SqlServer CTE 递归查询 Oracle递归查询

    在做数据库设计这块,很多时候表的数据模型就是典型的二叉树结构. 于是在查询数据的时候,就涉及到了数据的递归查询. 递归查询分为两种:1.从根节点查询自身以及所有的子节点:2.从子节点查询自身以及所有的 ...

  6. js 函数参数形式

    1. var a = function(b,c){ console.log(arguments);}a("1","cc"); ->  ["1&q ...

  7. wariging for you oh~

  8. ubuntu系统mysql.h no such file or directory

    在Ubuntu系统中,你已经安装了mysql,即你使用sudo apt-get install mysql-server mysql-client然而使用C语言访问mysql数据库时,却发现出现了如下 ...

  9. nuc900 nand flash mtd 驱动

    nuc900 nand flash mtd 驱动,请参考! /* * Copyright © 2009 Nuvoton technology corporation. * * Wan ZongShun ...

  10. Java简介(3)-基本语法

    1.大小写敏感 2.类名 3.方法名. 4.源文件名