链接器(linker)的作用——CSAPP第7章读书笔记_weixin_34391854的博客-程序员秘密

技术标签: 运维  c/c++  

  首先说说我为什么要去读这一章。这个学期开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两个表所记录的内容。

转载于:https://www.cnblogs.com/immortal-worm/p/5819036.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34391854/article/details/93318536

智能推荐

乐观锁与悲观锁_huaweitman的博客-程序员秘密

不知疲倦的猪可以怀疑我的水平,但是不能怀疑的人品!!BlogJava   首页   联系   聚合   管理随笔-109  评论-182  文章-25  trackbacks-0乐观锁与悲观锁文章转自网上好像是玉米田的,忘记了锁( locking ) 业务逻辑的实现过程中,往往需要保证数据访问的排他性。如在金融系统的日终结算 处理中,我们

自省篇_7_1_weixin_33815613的博客-程序员秘密

  最近有开始放松了。晚饭在食堂看见了软院的zcp,等饭菜的时候手里还捧着小红点。认真的程序猿真好看。我也要做认真的程序猿。 7月开始了,永远不要停止自我提升+外部环境提升。转载于:https://www.cnblogs.com/HughParker/p/4614831.html...

html 嵌入页面,html5页面嵌入_Scifi-gamer的博客-程序员秘密

8种机械键盘轴体对比本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?几个常见的h5嵌入标签的属性及用法介绍,包括iframe标签、embed标签以及script标签。 标签规定一个内联框架。一个内联框架被用来在当前 HTML 文档中嵌入另一个文档。所有主流浏览器都支持 标签。属性一些关于iframe的属性,注意以下仅是Hexo支持的的部分属性。关于iframe的src属性:| 属性 |...

上海地铁和Metro大都会手机应用的常见问题_大都会能够直接用nfc刷卡吗_安心攻略的博客-程序员秘密

内容提要综合问题大都会和NFC哪个刷卡更快?怎么快速知道每个地铁站的卫生间在哪里?大都会怎么关闭大都会的消息推送大都会可以在上海公交上刷卡吗?大都会可以刷卡乘坐磁悬浮吗?怎么更换支付方式?为什么大都会切换支付方式后要多久才能真正使用?为什么大都会切换支付方式后不能马上更换?怎么查找首末班车时间?怎么查找站点地图、站内设施、进出口位置、首末班时间?地铁Metro大...

【Halcon视觉】图像测量_distance_cc_文布斯的博客-程序员秘密

机器视觉的测量原理 基于机器视觉的检测过程:对感兴趣的对象或区域进行成像,然后结合其图像信息,利用图像处理软件进行处理,根据处理结果自动判断检测对象的位置,尺寸,外观信息,并依据人为预先设定的标准进行合格与否的判断,最后输出其判断信息给执行机构。机器视觉检测系统采用CCD相机或CMOS相机将被检测的对象信息转换成图像信号,传送给专用的图像处理软件,图像处理软件根据像素分布,亮度,颜色等信息,将图像信号,转变成数字化信号,并对这些信号进行各种运算,来抽取对象的特征,如面积,数...

bpmn-js绘制activiti工作流_bpm.js_peng_wei_kang的博客-程序员秘密

今天想大家分享一款js工作流绘制框架,它就是bpmn-js,他的网站地址是点击打开链接,通过这个框架可以在网页上编写工作流,支持在线编写并绑定业务,使用方法如下:首先需要安装bpmn-jsnpm install bpmn-js --save-dev安装好这个只能支持在线绘制工作流,而不能对工作流上的每个节点进行属性设置,这个时候需要安装bpmn-js的一个panel插件。npm install ...

随便推点

(NoPermissions (FileSystemError): Error: EACCES: permission denied, open_Elegantmumu的博客-程序员秘密

项目场景:在Linux 服务器,写入遇到权限问题,chmod 777 name 还是存在。(NoPermissions (FileSystemError): Error: EACCES: permission denied, open问题描述:(NoPermissions (FileSystemError): Error: EACCES: permission denied, open#需要修改用户sudo chown -R 你服务器的用户:name 目标文件原因分析:没有root用户权限,

通过返回栈的活动来理解Activity生命周期_活动返回栈_wapchief的博客-程序员秘密

Android中最常用的无非就是Activity, 而精通其中的原理和生命周期也是一个Android程序员必备的技能,包括在面试的时候很多问题都会涉及到activity生命周期。当我们启动一个app的时候,其实就已经开始了activity的生命, 而这一开始的activity就是MainActivity,基本在我们创建应用的时候就存在了。下面一张图来帮助我们了解生命周期。Activity中一共有

Android Binder学习(三)之defaultServiceManager()的分析_armwind的博客-程序员秘密

Android Binder学习(三)之defaultServiceManager()的分析  文章还是按着函数调用的顺序来分析的。这里我们就在mediaServer进程中研究一下,serviceManage代理对象的获取过程。首先看到的就是mediaServer进程中的main函数了。下面可以看到meidaServer进程注册很多和多媒体相关的服务。int main(int argc __unus

WMI完美秀出CPU编号厂商主频电压等全部信息_wmi cpu l1_waxic的博客-程序员秘密

主页:http://blog.csdn.net/21aspnet/           时间:2007.3.23 关于WMI MSDN有详细说明。 本文列举数例算抛砖引玉吧。WMI是个好东西,看过本文后也许你应该能举一反三参考MSDN也许自己做个优化大师也是可能的。本文的例子在以下环境调试通过:Windows2003+AMD64双核CPU+VisualStudio2005(C#)下调试通过

存储过程中日期格式的转换_储存过程 date类型转_江南小小生的博客-程序员秘密

其实写存储过程就相当于在下写有逻辑的SQL。存储过程中的时类有:ADDTIME (date2 ,time_interval ) //将time_interval加到date2CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //转换时区CURRENT_DATE (  ) //当前日期CURRENT_TIME (  ) //当前时间CURRENT_T

java中status_Java中System.exit(status)和Runtime.getRuntime().halt(status)区别_intimetoavaid的博客-程序员秘密

System.exit(status);Runtime.getRuntime().halt(status)这两个都表示系统退出,那么他们有什么区别呢?针对System.exit(status)解释如下:Terminates the currently running Java Virtual Machine. Theargument serves as a status code; by conv...

推荐文章

热门文章

相关标签