Appearance
题目
在虚拟内存管理中,地址变换机构将逻辑地址变换为物理地址,形成该逻辑地址的阶段是( )。
错因
A
编辑只是写代码——产生的是源文件(.c / .cpp),里面是变量名、函数名等符号,根本没有"地址"这个概念。把"写代码"当成"形成地址"是把开发流程的最早阶段误以为有地址输出。
B
编译产生目标文件(.o / .obj)——里面有针对单个翻译单元的相对地址(段内偏移),但模块间的引用还是符号(跨文件函数调用、外部变量都是未解析的符号)。所以"完整的逻辑地址"在编译这一步还没形成,要到链接才合成。
D
装载是把可执行文件搬到内存——分静态装载(直接按链接好的逻辑地址装到对应物理位置)和动态装载(运行时按需装入)。逻辑地址在链接时就定了,装载时只是把内容搬进去,地址早已确定,不是"形成"逻辑地址。
总解析
程序的"地址"演化:
| 阶段 | 输入 | 输出 | 地址形态 |
|---|---|---|---|
| 编辑 | 源代码 | 源文件 .c | 符号(变量名、函数名) |
| 编译 | 单个 .c | 目标文件 .o | 段内偏移(每个 .o 内部相对地址,跨 .o 的引用还是符号) |
| 链接 | 多个 .o + 库 | 可执行文件 a.out | 完整的逻辑地址——所有符号被解析、各模块地址重定位、合成统一的逻辑地址空间 |
| 装载 | 可执行文件 | 进程内存映像 | 把逻辑地址装到(虚拟)内存,逻辑地址不变 |
| 运行时(地址变换) | 逻辑地址 | 物理地址 | MMU 通过页表 / 段表把逻辑地址变换成物理地址 |
关键节点:链接是合成逻辑地址的最后一步——之前各模块只有自己的内部地址,链接负责"把所有 .o 拼成一个大整体,给每个符号确定的逻辑地址"。
链接做的事(细节):
- 符号解析:把"调用 printf"这种符号引用解决到具体地址
- 重定位:把各个 .o 段内部地址按"链接脚本"映射到统一的逻辑地址空间(如 .text 从 0x4000 开始、.data 紧随其后)
- 最终输出:每条指令、每个变量都有了确定的逻辑地址
装载只是把这个地址映射到物理内存的某段,地址变换在 MMU 里把逻辑地址翻译成物理地址——但逻辑地址本身的"出生"在链接阶段。
最终答案是 C。