我试图了解内存管理如何在低水平上进行,并有几个问题。
1) Kip R. Irvine 写的一本关于汇编语言的书说,在实模式下,程序启动时前三个段寄存器会加载代码、数据和堆栈段的基地址。这对我来说有点模棱两可。这些值是手动指定的还是汇编器生成指令将这些值写入寄存器?如果它自动发生,它如何找出这些段的大小?
2)我知道Linux使用平面线性模型,即以非常有限的方式使用分段。另外,根据 Daniel P. Bovet 和 Marco Cesati 所著的《Understanding the Linux Kernel》,GDT 中有四个主要部分:用户数据、用户代码、内核数据和内核代码。所有四个段都具有相同的大小和基地址。我不明白为什么需要其中四个,如果它们仅在类型和访问权限上不同(它们都产生相同的线性地址,对吧?)。为什么不只使用其中之一并将其描述符写入所有段寄存器?
3)不使用分段的操作系统如何将程序划分为逻辑段?例如,他们如何区分堆栈和没有段描述符的代码。我读到分页可以用来处理这样的事情,但不明白如何做。
-
你一定读过一些非常老的书,因为没有人为实模式不再;-) 在实模式,您可以使用以下命令获取内存访问的物理地址physical address = segment register * 0x10 + offset
,偏移量是通用寄存器之一内的值。因为这些寄存器是 16 位宽,所以一个段的长度为 64kb,并且您无法对其大小进行任何操作,因为没有属性!随着* 0x10
乘法,1MB 内存变为可用,但是根据您放入的内容,存在重叠组合段寄存器和地址寄存器。我还没有编译任何代码实模式,但我认为这取决于操作系统来设置段寄存器在二进制加载期间,就像加载器在加载 ELF 二进制文件时会分配一些页面一样。然而,我确实编译了裸机内核代码,并且我必须自己设置这些寄存器。
-
由于架构限制,扁平模型中必须有四个部分。在保护模式 the 段寄存器不再包含段基地址,而是包含段选择器这基本上是 GDT 的偏移量。取决于值段选择器,CPU将处于给定的特权级别,这就是CPL(当前特权级别)。这段选择器指向一个段描述符它有一个 DPL(描述符特权级别),如果段寄存器充满了这个选择器(至少对于代码段选择器来说是这样)。因此你至少需要一双段选择器以区分内核和用户区。此外,段要么是代码段,要么是数据段,所以最终会得到四个段描述符在 GDT 中。
-
我没有任何使用分段的严肃操作系统的示例,只是因为分段仍然存在以实现向后兼容。使用平面模型方法只不过是摆脱它的一种手段。不管怎样,你是对的,分页更加高效和通用,并且几乎可以在所有架构上使用(至少在概念上)。我无法在这里解释分页内部结构,但是您需要了解的所有信息都在优秀的 Intel man 中:英特尔® 64 和 IA-32 架构
软件开发人员手册
第 3A 卷:
系统编程指南,第 1 部分 http://download.intel.com/products/processor/manual/253668.pdf
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)