4.2 程序的装入和链接
L23
学习目标
页表、地址变换;段表与段的逻辑意义。为第五章虚存打基础。
- 页是物理管理单位,段是逻辑单位。
- 无 MMU 的 MCU 用「编译期分区」近似。
- 对换区、换出进程。
- 本课不实现 swapping。
- 虚存是 OS+硬件协同。
- 本课以原理+动画为主,不在 C5 教学内核实现完整请求页。
- 内部/外部碎片。
- 首次适应等分配策略。
原理 · 深入理解
4.2 程序的装入和链接
用户程序运行前须经编译、链接、装入三步,将源程序转为可执行内存映像。
- 编译:编译程序将源程序编译成目标模块
- 链接:链接程序将目标模块与库函数链接成装入模块
- 装入:装入程序将装入模块装入内存
4.2.1 程序的装入
单道程序环境下可预知程序驻留位置,采用绝对装入:编译产生绝对地址目标代码。
程序使用符号地址,编译或汇编时转为绝对地址;也可由程序员直接赋予。
- 三种装入方式:绝对装入、可重定位装入、动态运行时装入
可重定位装入允许装入到任意允许位置,但不允许运行时在内存中移动。
动态运行时装入把地址转换推迟到程序真正执行时才进行,便于程序运行中移动位置。
多道环境下编译程序无法预知目标模块在内存位置,绝对装入不再适用。
目标模块起始地址通常从0开始,其它地址相对起始计算,应按内存情况装入到适当位置。
4.2.2 程序的链接
静态链接在运行前将各目标模块及库函数链接成完整装配模块,以后不再拆开。
- 对相对地址进行修改
- 变换外部调用符号
须解决两个问题:修改相对地址、变换外部调用符号。
装入时动态链接(Load-time Dynamic Linking)
装入时动态链接指将用户源程序编译后所得到的一组目标模块,在装入内存时,采用边装入边链接的链接方式。即在装入一个目标模块时,若发生一个外部模块调用事件,将引起装入程序去找出相应的外部目标模块,并将它装入内存,还要按照图4-4所示的方式修改目标模块中的相对地址。 装入时动态链接方式有以下优点。
- 便于修改和更新
- 便于实现对目标模块的共享
运行时动态链接(Run-time Dynamic Linking)
低效→在许多情况下,应用程序在运行时,每次要运行的模块可能是不相同的。但由于事先无法知道本次要运行哪些模块,故只能是将所有可能要运行到的模块全部都装入内存,并在装入时全部链接在一起。
运行时动态链接方式: 将对某些模块的链接推迟到程序执行时才进行,在执行过程中,当发现一个被调用模块尚未装入内存时,立即由OS去找到该模块,并将之装入内存,将其链接到调用者模块上。凡在执行过程中未被用到的目标模块,都不会被调入内存和被链接到装入模块上。
做 · 实验
- 根据「学习目标」列出 3 个关键词,对照原理段落解释给自己听。
- 完成 06-heap 或等价练习:分配-释放-再分配观察。
程序的装入和链接
swapping
用控件单步操作;日志区记下每一步发生了什么。
代码导读
本课在工作台编译烧录。先读 user 实验入口,再对照 kernel / HDF 中被调用的函数,不要一上来改链接脚本。
总结与提升
- 能对比页式与段式的优缺点各一条。
- 能用自己的话复述学习目标,并指出概念与板上实验的对应。
- 能说明 MCU 课为何跳过对换实验。
- 能说出虚存依赖的硬件支持。
- 能区分内碎片与外碎片。
- 能结合动画解释一次分配失败原因。
- 能说出 Flash 与 DRAM 在链接中的角色。
延伸思考
- ESP32 的 MMU/Cache 与教材页表哪一层接近?
- 如果把本节机制拿到 Linux 或完整 OpenHarmony 上,会多出哪些硬件假设?
- 把进程映像存到 Flash 文件系统算对换吗?
- 没有缺页中断能否做虚存?