《深入浅出计算机组成原理》学习笔记 Day5

1. 静态链接与动态链接

静态链接(Static Link)是通过合并代码段的方法来使程序装载至内存;
动态链接(Dynamic Link)则是链接加载到内存中的共享库(Shared Libraries)。

在 Windows 下,这些共享库文件就是 .dll 文件,也就是 Dynamic-Link Library(DLL,动态链接库)。

在 Linux 下,这些共享库文件就是 .so 文件,也就是 Shared Object(动态链接库)。

2. 地址无关

在程序运行的时候共享代码,这些机器码必须满足地址无关。也就是说,编译出来的共享库文件的指令代码,是地址无关码(Position-Independent Code)。即,这段代码无论加载在哪个内存地址,都能够正常执行。

而常见的地址相关的代码,比如绝对地址代码(Absolute Code)、利用重定位表的代码等,都是地址相关的代码。例如重定位表,在程序链接的时候,就把函数调用后要跳转访问的地址确定下来了,这意味着,如果这个函数加载到一个不同的内存地址,跳转就会失败。

在这里插入图片描述
对于所有动态链接共享库的程序来讲,虽然共享库用的都是同一段物理内存地址,但是在不同的应用程序里,它所在的虚拟内存地址是不同的。

我们没办法、也不应该要求动态链接同一个共享库的不同程序,必须把这个共享库所使用的虚拟内存地址变成一致。如果这样的话,我们写的程序就必须明确地知道内存的内存地址分配。

动态代码库内部的变量和函数调用都很容易解决,我们只需要使用相对地址(Relative Address)就好了。各种指令中使用到的内存地址,给出的不是一个绝对的地址空间,而是一个相对于当前指令偏移量的内存地址。因为整个共享库是放在一段连续的虚拟内存地址中的,无论装载到哪一段地址,不同指令之间的相对地址都是不变的。

3. PLT 和 GOT

PLT程序链接表(Procedure Link Table)。

在共享库的 data section 里面,保存了一张 全局偏移表(GOT,Global Offset Table)。虽然共享库的代码部分的物理内存是共享的,但是数据部是使用动态链接的应用程序里面各加载一份的

所有需要引用当前共享库外部的地址的指令,都会查询 GOT,来找到当前运行程序的虚拟内存里的对应位置。而 GOT 表里面的数据,则是在加载一个个共享库的时候写进去的。

不同的进程,调用同样的动态链接文件,各自 GOT 里面指向最终加载的动态链接库里面的虚拟内存地址是不同的。

这样,虽然不同的程序调用的同样的动态库,各自的内存地址是独立的,调用的又都是同一个动态库,但是不需要去修改动态库里面的代码所使用的地址,而是各个程序各自维护好自己的 GOT,能够找到对应的动态库就好了。

我们的 GOT 表位于共享库自己的数据段里。GOT 表在内存里和对应的代码段位置之间的偏移量,始终是确定的。这样,我们的共享库就是地址无关的代码,对应的各个程序只需要在物理内存里面加载同一份代码。而我们又要通过各个可执行程序在加载时,生成的各不相同的 GOT 表,来找到它需要调用到的外部变量和函数的地址。

参考

极客时间《深入浅出计算机组成原理》:http://gk.link/a/11UMi

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Balaaam

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值