深入浅出计算机组成原理
徐文浩
bothub创始人
立即订阅
13019 人已学习
课程目录
已完结 62 讲
0/4登录后,你可以任选4讲全文学习。
入门篇 (5讲)
开篇词 | 为什么你需要学习计算机组成原理?
免费
01 | 冯·诺依曼体系结构:计算机组成的金字塔
02 | 给你一张知识地图,计算机组成原理应该这么学
03 | 通过你的CPU主频,我们来谈谈“性能”究竟是什么?
04 | 穿越功耗墙,我们该从哪些方面提升“性能”?
原理篇:指令和运算 (12讲)
05 | 计算机指令:让我们试试用纸带编程
06 | 指令跳转:原来if...else就是goto
07 | 函数调用:为什么会发生stack overflow?
08 | ELF和静态链接:为什么程序无法同时在Linux和Windows下运行?
09 | 程序装载:“640K内存”真的不够用么?
10 | 动态链接:程序内部的“共享单车”
11 | 二进制编码:“手持两把锟斤拷,口中疾呼烫烫烫”?
12 | 理解电路:从电报机到门电路,我们如何做到“千里传信”?
13 | 加法器:如何像搭乐高一样搭电路(上)?
14 | 乘法器:如何像搭乐高一样搭电路(下)?
15 | 浮点数和定点数(上):怎么用有限的Bit表示尽可能多的信息?
16 | 浮点数和定点数(下):深入理解浮点数到底有什么用?
原理篇:处理器 (18讲)
17 | 建立数据通路(上):指令+运算=CPU
18 | 建立数据通路(中):指令+运算=CPU
19 | 建立数据通路(下):指令+运算=CPU
20 | 面向流水线的指令设计(上):一心多用的现代CPU
21 | 面向流水线的指令设计(下):奔腾4是怎么失败的?
22 | 冒险和预测(一):hazard是“危”也是“机”
23 | 冒险和预测(二):流水线里的接力赛
24 | 冒险和预测(三):CPU里的“线程池”
25 | 冒险和预测(四):今天下雨了,明天还会下雨么?
26 | Superscalar和VLIW:如何让CPU的吞吐率超过1?
27 | SIMD:如何加速矩阵乘法?
28 | 异常和中断:程序出错了怎么办?
29 | CISC和RISC:为什么手机芯片都是ARM?
30 | GPU(上):为什么玩游戏需要使用GPU?
31 | GPU(下):为什么深度学习需要使用GPU?
32 | FPGA和ASIC:计算机体系结构的黄金时代
33 | 解读TPU:设计和拆解一块ASIC芯片
34 | 理解虚拟机:你在云上拿到的计算机是什么样的?
原理篇:存储与I/O系统 (17讲)
35 | 存储器层次结构全景:数据存储的大金字塔长什么样?
36 | 局部性原理:数据库性能跟不上,加个缓存就好了?
37 | 高速缓存(上):“4毫秒”究竟值多少钱?
38 | 高速缓存(下):你确定你的数据更新了么?
39 | MESI协议:如何让多核CPU的高速缓存保持一致?
40 | 理解内存(上):虚拟内存和内存保护是什么?
41 | 理解内存(下):解析TLB和内存保护
42 | 总线:计算机内部的高速公路
43 | 输入输出设备:我们并不是只能用灯泡显示“0”和“1”
44 | 理解IO_WAIT:I/O性能到底是怎么回事儿?
45 | 机械硬盘:Google早期用过的“黑科技”
46 | SSD硬盘(上):如何完成性能优化的KPI?
47 | SSD硬盘(下):如何完成性能优化的KPI?
48 | DMA:为什么Kafka这么快?
49 | 数据完整性(上):硬件坏了怎么办?
50 | 数据完整性(下):如何还原犯罪现场?
51 | 分布式计算:如果所有人的大脑都联网会怎样?
应用篇 (5讲)
52 | 设计大型DMP系统(上):MongoDB并不是什么灵丹妙药
53 | 设计大型DMP系统(下):SSD拯救了所有的DBA
54 | 理解Disruptor(上):带你体会CPU高速缓存的风驰电掣
55 | 理解Disruptor(下):不需要换挡和踩刹车的CPU,有多快?
结束语 | 知也无涯,愿你也享受发现的乐趣
免费
答疑与加餐 (5讲)
特别加餐 | 我在2019年F8大会的两日见闻录
FAQ第一期 | 学与不学,知识就在那里,不如就先学好了
用户故事 | 赵文海:怕什么真理无穷,进一寸有一寸的欢喜
FAQ第二期 | 世界上第一个编程语言是怎么来的?
特别加餐 | 我的一天怎么过?
深入浅出计算机组成原理
登录|注册

10 | 动态链接:程序内部的“共享单车”

徐文浩 2019-05-17
我们之前讲过,程序的链接,是把对应的不同文件内的代码段,合并到一起,成为最后的可执行文件。这个链接的方式,让我们在写代码的时候做到了“复用”。同样的功能代码只要写一次,然后提供给很多不同的程序进行链接就行了。
这么说来,“链接”其实有点儿像我们日常生活中的标准化、模块化生产。我们有一个可以生产标准螺帽的生产线,就可以生产很多个不同的螺帽。只要需要螺帽,我们都可以通过链接的方式,去复制一个出来,放到需要的地方去,大到汽车,小到信箱。
但是,如果我们有很多个程序都要通过装载器装载到内存里面,那里面链接好的同样的功能代码,也都需要再装载一遍,再占一遍内存空间。这就好比,假设每个人都有骑自行车的需要,那我们给每个人都生产一辆自行车带在身边,固然大家都有自行车用了,但是马路上肯定会特别拥挤。

链接可以分动、静,共享运行省内存

我们上一节解决程序装载到内存的时候,讲了很多方法。说起来,最根本的问题其实就是内存空间不够用。如果我们能够让同样功能的代码,在不同的程序里面,不需要各占一份内存空间,那该有多好啊!就好比,现在马路上的共享单车,我们并不需要给每个人都造一辆自行车,只要马路上有这些单车,谁需要的时候,直接通过手机扫码,都可以解锁骑行。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入浅出计算机组成原理》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(45)

  • 胖胖胖
    所以说plt 里面实际上是存放了 GOT[ i ] 的地址 , 而 GOT[ i ] 中存放了 要调用函数在虚拟内存中的地址,而该地址实际上是共享函数代码段的真实物理地址的一个映射。但有一些疑问,PLT 的 机制是什么,感觉没太介绍PLT ,不知道他怎么来的。对PLT 很模糊,他如何利用了相对地址的方法。希望老师能解答一下
    2019-05-17
    2
    16
  • Calix
    1. GOT 保存在共享库自己的数据段里
    2. 每个程序维护自己的GOT

    所以,GOT 到底保存在哪里??共享库里面还是各个程序里?
    2019-05-24
    2
    8
  • cbing
    在动态链接对应的共享库,我们在共享库的 data section 里面,保存了一张全局偏移表(GOT,Global Offset Table)。虽然共享库的代码部分的物理内存是共享的,但是数据部分是各个动态链接它的应用程序里面各加载一份的。所有需要引用当前共享库外部的地址的指令,都会查询 GOT,来找到当前运行程序的虚拟内存里的对应位置。而 GOT 表里的数据,则是在我们加载一个个共享库的时候写进去的。
    -------------------
    老师可不可以重新解释下这一段啊,特别是“所有需要引用当前共享库外部的地址的指令,都会查询 GOT,来找到当前运行程序的虚拟内存里的对应位置”这一句,好懵
    2019-05-19
    6
  • cbing
    在动态链接对应的共享库,我们在共享库的 data section 里面,保存了一张全局偏移表(GOT,Global Offset Table)。虽然共享库的代码部分的物理内存是共享的,但是数据部分是各个动态链接它的应用程序里面各加载一份的。所有需要引用当前共享库外部的地址的指令,都会查询 GOT,来找到当前运行程序的虚拟内存里的对应位置。而 GOT 表里的数据,则是在我们加载一个个共享库的时候写进去的。
    --------------
    这段完全看不懂QAQ
    2019-05-19
    6
  • Java语言多态的实现

    作者回复: 👍不错的例子

    2019-05-17
    1
    5
  • 半斤八两
    所以老师请问下GOT是每个程序都维护一张所以有多张还是每个程序共同维护一张GOT

    作者回复: 每个程序自己维护一张

    2019-05-23
    4
  • 许山山
    真的写的好棒啊,和操作系统配合食用简直不要太爽

    作者回复: 谢谢支持

    2019-05-17
    4
  • fatme
    老师,为什么要采用 PLT 和 GOT 两级跳转,直接用 GOT 有问题吗?

    作者回复: PLT是为了做延迟绑定,如果函数没有实际被调用到,就不需要更新GOT里面的数值。因为很多动态装载的函数库都是不会被实际调用到的。

    这个如果要深入细节可以看一下《程序员的自我修养》的7.4小结。

    2019-09-20
    3
  • 阿锋
    有一个点不明白,虚拟内存中的内容究竟放在哪里,它的内容也应该是放在物理内存里的或者是硬盘里的?是这样吗?

    作者回复: 是的,虚拟内存既然叫做“虚拟”它就是一个抽象概念。要么是已经实际加载到物理内存里了,要么还没有加载或者交换出去在硬盘上。

    2019-05-23
    3
  • 栋能
    看了GOT表之后的那个图(动态链接过程图)我有个疑问,我们的程序在虚拟内存中还是像静态链接那样,把需要的库都加载(拼接)进来的,故调用的共享库在程序的虚拟内存空间中其实还是多份的?还有就是如果GOT在共享库的data section,那不同程序调用的时候,如何区分当前GOT属于那个程序呢?
    2019-05-22
    1
    3
  • 焰火
    浩哥您好,有个问题想请教一下您。
    共享库在内存中也是采用分页机制么? 如果是的话,那么怎么解决多进程同时调用共享库的问题呢?
    如果不是的话,那么这共享库在内存里就是全加载?

    作者回复: 焰火同学你好

    这是个好问题,共享库在内存中也是采用分页机制的。
    同时调用共享库只要对应的指令代码是PIC的也就是地址无关的,并不会有什么问题。但是两个进程的数据段是不共享的而已。

    2019-05-21
    3
  • 活的潇洒
    这一周紧赶慢赶,总算是赶上了更新的进度。day10天学习笔记
    https://www.cnblogs.com/luoahong/p/10880416.html

    作者回复: 👍坚持到底就是胜利

    2019-05-17
    3
  • 冯华琴也可叫做冯琴华
    动态代理?上层应用只和代理类交互,具体实现是透明的。

    作者回复: 👍动态代理是个不错的例子

    2019-05-17
    2
  • 一步
    每个应用程序都会生成自己的GOT表吗?

    作者回复: 不使用动态链接的话就不需要啊

    2019-05-19
    1
  • Geek_648105
    多个应用程序同时调用同一个库,不是有重入的问题吗?库应该是用可重入的方式写吗?我反复看了几遍,对于库是不太理解。
    2019-05-18
    1
  • Allen
    老师可以加一节课,讲解一下如何利用栈信息,来解栈调用关系吗?

    比如:C程序发生段错误,利用黑匣子日志,如何分析 段错误时,函数的堆栈信息吗?

    作者回复: Allen同学你好,

    这个需要的前置知识有点多,而且不太方便用文章的形式体现。先要教会大家用gbd,然后一步一步调试,也不太适合录音。

    我想想是否有可能在专栏结束之后用加餐的形式提供一些对应的内容。

    2019-05-18
    1
  • Sentry
    mac机器上objdump命令-M选项有问题,请老师确认下该如何处理,谢谢。

    作者回复: 抱歉手头没有mac,我看看稍后抽空研究一下,不过不使用-M一样可以看到对应的指令信息,只是可能格式稍有不同,应该不影响理解指令含义。

    2019-05-17
    1
  • Milittle
    plt应该是在链接动态库时候生成的。
    不知道理解是否正确
    2019-05-17
    1
  • 青莲
    多态算吗

    作者回复: 如果算的话,你认为是为什么呢?

    2019-05-17
    1
  • 王加武
    动态链接就是来解决静态链接缺陷的一种方式!
    2019-12-10
收起评论
45
返回
顶部