10 | 动态链接:程序内部的“共享单车”
徐文浩
该思维导图由 AI 生成,仅供参考
我们之前讲过,程序的链接,是把对应的不同文件内的代码段,合并到一起,成为最后的可执行文件。这个链接的方式,让我们在写代码的时候做到了“复用”。同样的功能代码只要写一次,然后提供给很多不同的程序进行链接就行了。
这么说来,“链接”其实有点儿像我们日常生活中的标准化、模块化生产。我们有一个可以生产标准螺帽的生产线,就可以生产很多个不同的螺帽。只要需要螺帽,我们都可以通过链接的方式,去复制一个出来,放到需要的地方去,大到汽车,小到信箱。
但是,如果我们有很多个程序都要通过装载器装载到内存里面,那里面链接好的同样的功能代码,也都需要再装载一遍,再占一遍内存空间。这就好比,假设每个人都有骑自行车的需要,那我们给每个人都生产一辆自行车带在身边,固然大家都有自行车用了,但是马路上肯定会特别拥挤。
链接可以分动、静,共享运行省内存
我们上一节解决程序装载到内存的时候,讲了很多方法。说起来,最根本的问题其实就是内存空间不够用。如果我们能够让同样功能的代码,在不同的程序里面,不需要各占一份内存空间,那该有多好啊!就好比,现在马路上的共享单车,我们并不需要给每个人都造一辆自行车,只要马路上有这些单车,谁需要的时候,直接通过手机扫码,都可以解锁骑行。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了动态链接的概念和实现方式。通过动态链接,程序可以在内存中共享代码,节省内存空间。文章详细讨论了动态链接的实现过程,包括动态链接库的创建和调用过程。通过动态链接,不同程序可以共享同一份代码,实现了代码在运行阶段的复用。此外,文章还提到了动态链接在Linux下的应用,以及动态链接的重要性和优势。总的来说,动态链接通过修改“地址数据”来进行间接跳转,实现了代码的灵活调用,为程序开发带来了便利和效率提升。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入浅出计算机组成原理》,新⼈⾸单¥68
《深入浅出计算机组成原理》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(82)
- 最新
- 精选
- fatme老师,为什么要采用 PLT 和 GOT 两级跳转,直接用 GOT 有问题吗?
作者回复: PLT是为了做延迟绑定,如果函数没有实际被调用到,就不需要更新GOT里面的数值。因为很多动态装载的函数库都是不会被实际调用到的。 这个如果要深入细节可以看一下《程序员的自我修养》的7.4小结。
2019-09-20351 - 齐Java语言多态的实现
作者回复: 👍不错的例子
2019-05-17541 - 许山山真的写的好棒啊,和操作系统配合食用简直不要太爽
作者回复: 谢谢支持
2019-05-17221 - 半斤八两所以老师请问下GOT是每个程序都维护一张所以有多张还是每个程序共同维护一张GOT
作者回复: 每个程序自己维护一张
2019-05-23419 - 阿锋有一个点不明白,虚拟内存中的内容究竟放在哪里,它的内容也应该是放在物理内存里的或者是硬盘里的?是这样吗?
作者回复: 是的,虚拟内存既然叫做“虚拟”它就是一个抽象概念。要么是已经实际加载到物理内存里了,要么还没有加载或者交换出去在硬盘上。
2019-05-2319 - 焰火浩哥您好,有个问题想请教一下您。 共享库在内存中也是采用分页机制么? 如果是的话,那么怎么解决多进程同时调用共享库的问题呢? 如果不是的话,那么这共享库在内存里就是全加载?
作者回复: 焰火同学你好 这是个好问题,共享库在内存中也是采用分页机制的。 同时调用共享库只要对应的指令代码是PIC的也就是地址无关的,并不会有什么问题。但是两个进程的数据段是不共享的而已。
2019-05-21215 - 冯华琴也可叫做冯琴华动态代理?上层应用只和代理类交互,具体实现是透明的。
作者回复: 👍动态代理是个不错的例子
2019-05-1713 - 活的潇洒这一周紧赶慢赶,总算是赶上了更新的进度。day10天学习笔记 https://www.cnblogs.com/luoahong/p/10880416.html
作者回复: 👍坚持到底就是胜利
2019-05-1727 - 奕每个应用程序都会生成自己的GOT表吗?
作者回复: 不使用动态链接的话就不需要啊
2019-05-196 - yang在mac上面好像看不出来 PLT 和 GOT 的存在 objdump -source show_me_poor show_me_poor: file format Mach-O 64-bit x86-64 Disassembly of section __TEXT,__text: __text: 100000f70: 55 pushq %rbp 100000f71: 48 89 e5 movq %rsp, %rbp 100000f74: 48 83 ec 10 subq $16, %rsp 100000f78: c7 45 fc 05 00 00 00 movl $5, -4(%rbp) 100000f7f: 8b 7d fc movl -4(%rbp), %edi 100000f82: e8 09 00 00 00 callq 9 <dyld_stub_binder+0x100000f90> 100000f87: 31 c0 xorl %eax, %eax 100000f89: 48 83 c4 10 addq $16, %rsp 100000f8d: 5d popq %rbp 100000f8e: c3 retq _main: 100000f70: 55 pushq %rbp 100000f71: 48 89 e5 movq %rsp, %rbp 100000f74: 48 83 ec 10 subq $16, %rsp 100000f78: c7 45 fc 05 00 00 00 movl $5, -4(%rbp) 100000f7f: 8b 7d fc movl -4(%rbp), %edi 100000f82: e8 09 00 00 00 callq 9 <dyld_stub_binder+0x100000f90> 100000f87: 31 c0 xorl %eax, %eax 100000f89: 48 83 c4 10 addq $16, %rsp 100000f8d: 5d popq %rbp 100000f8e: c3 retq Disassembly of section __TEXT,__stubs: __stubs: 100000f90: ff 25 7a 00 00 00 jmpq *122(%rip) Disassembly of section __TEXT,__stub_helper: __stub_helper: 100000f98: 4c 8d 1d 69 00 00 00 leaq 105(%rip), %r11 100000f9f: 41 53 pushq %r11 100000fa1: ff 25 59 00 00 00 jmpq *89(%rip) 100000fa7: 90 nop 100000fa8: 68 00 00 00 00 pushq $0 100000fad: e9 e6 ff ff ff jmp -26 <__stub_helper> mac 下好像是 100000f82: e8 09 00 00 00 callq 9 <dyld_stub_binder+0x100000f90> dyld_stub_binder 不过,算是知道或者说了解了共享库是通过动态链接 动态生成共享代码的地址,而这个地址一方面是在运行的时候生成,另一方面取决于当前指令的相对地址。这里面有两个重要的表叫PLT(程序链接表)和 GOT(全局位移表)。 额,忽然想起来了一个词语,叫动态绑定,就是运行时才知道是哪个实现。 而静态绑定,就是在编译的时候就已经确定了是哪个实现。 要更好的理解这一讲,需要结合老师推荐的书和linux 环境。
作者回复: gogo同学, 你好,是的,动态绑定其实和动态链接本质上就是同一个思路。 要看对应的汇编代码,可以找一台云主机装一下Linux,Mac下连readelf这样可以读取elf格式的命令也没有。
2020-01-033
收起评论