【发布时间】:2019-04-21 02:14:27
【问题描述】:
在分段方案中,每次进行内存访问时,MMU 都会通过查找段表进行从到实际地址的转换。
段表是存储在 TLB 中还是存储在 RAM 中?
【问题讨论】:
标签: memory-management operating-system memory-segmentation
在分段方案中,每次进行内存访问时,MMU 都会通过查找段表进行从到实际地址的转换。
段表是存储在 TLB 中还是存储在 RAM 中?
【问题讨论】:
标签: memory-management operating-system memory-segmentation
段表是存储在 TLB 中还是 RAM 中?
这取决于 CPU 的类型和 CPU 所处的模式。
对于 80x86,当加载段寄存器时,CPU 将段的“基地址、限制和属性”存储在段寄存器的隐藏部分中。
对于实模式、virtual8086 模式和系统管理模式,当加载段寄存器时,CPU 只是执行“隐藏段基数 = 段值 * 16”,并且 RAM 中没有表。
对于保护模式和长模式,当加载段寄存器时,CPU 使用加载到段寄存器中的值作为 RAM 中表的索引,并且(在进行保护检查后)加载“基地址,限制和属性”信息从对应的表项到段寄存器的隐藏部分中。
请注意,(对于保护模式)几乎没有人使用分段,因为段寄存器加载速度很慢(由于保护检查和表查找);因此 CPU 制造商针对“无分段”优化了 CPU(例如,如果段基数为零,则现代 CPU 不会执行“线性地址 = 虚拟地址 + 段基数”,而只会执行“线性地址 = 虚拟地址”并避免不必要的添加并更快地开始缓存/内存查找)并且也没有费心优化段寄存器加载;然后当 AMD 设计长模式时,他们意识到没有人想要分段,并为 64 位代码禁用了大部分分段(忽略大多数段寄存器的段基数以摆脱额外的加法,并忽略段限制以摆脱段的成本限制检查)。但是,不使用分段的操作系统使用gs 和fs 作为黑客来快速访问特定于 CPU 或特定于线程的数据(因为,与其他一些 CPU 不同,80x86 没有只能由更方便的主管代码修改);因此 AMD 保留了这 2 个段寄存器的“线性地址 = 虚拟地址 + 段基址”行为,并增加了修改 gs 和 fs 的隐藏“基址”部分的能力(通过 MSR 和 swapgs)以便更轻松地将操作系统 (Windows) 移植到长模式。
换句话说,对于 80x86,有 3 种不同的方式来设置分段的信息(通过计算、通过表查找或通过 MSR)。
还要注意,对于大多数指令(不包括段寄存器加载之类的东西),80x86 CPU 不关心段信息是如何设置的,只使用段寄存器的隐藏部分。这意味着 CPU 不必在每次从 cs 获取代码时和每次从内存中获取数据时都查阅表。这也意味着大多数 CPU 并不关心 CPU 处于哪种模式(例如,mov eax,[ds:address] 之类的指令仅依赖于段寄存器隐藏部分中的值,而不依赖于 CPU 模式);这就是为什么移除过时的 CPU 模式没有任何好处(移除对实模式的支持不会减少 CPU 的大小或复杂性)。
对于其他 CPU;大多数不支持分段(仅支持分页或不支持),而且我不熟悉它对任何支持它的人的工作方式。但是,我怀疑每次获取任何内容时任何 CPU 都会进行表查找(这太慢/太贵而无法实用);我希望对于所有支持分段的 CPU,“当前使用”段的信息都会以某种方式在内部存储。
【讨论】:
段表是您使用内存时的参考。所以表必须永久存储以备后用,所以它存储在物理地址,即 RAM 中。
【讨论】: