我设法访问了multiboot_info_t
i386 内核中的 GRUB 多重引导信息结构 ( ),其中有两个字段分别称为mem_lower
和mem_upper
。如何使用它们来获取可用的总 RAM(以字节为单位)?
1 回答
简单地说,你不能。
mem_lower
和是过时的mem_upper
字段,指的是常规内存和扩展内存。
引用规格:
如果设置了字中的位 0
flags
,则mem_*
字段有效。
mem_lower
并mem_upper
分别以千字节千比字节表示低位和高位内存的数量。低位存储器从地址 0 开始,高位存储器从地址 1
兆字节开始。较低内存的最大可能值为 640KB。为高端内存返回的值最大为第一个高端内存孔的地址减去 1
兆字节。不保证是这个值。
这段摘录的两个关键方面是:
flags
在访问字段之前需要对该字段进行测试mem_*
。mem_lower
and字段对内存漏洞的mem_upper
处理非常糟糕。特别是mem_upper
保持扩展内存的第一个连续块的大小,直到第一个孔。
第二点非常重要,值得进一步讨论。
虽然内存本身可以被访问,但在内存控制器级别1,作为一个连续块,它在内存子系统级别是不连续的(曾经是北桥,现在是非核心)。
内存子系统通过简单地不回收特定的子范围(从而浪费该内存)或通过将子范围移动到更高地址来在分配给内存的连续地址范围中 创建空洞。
这种看似奇怪的行为背后的原因深深植根于 IBM PC 的历史演变。
完整的讨论不在主题范围内,但可以列出一个简短的版本。最初,IBM 为常规内存保留了 1MiB 地址空间中的前 640KiB,其余 384KiB 用于映射 ROM——包括 BIOS ROM。
请注意,内存控制器不得响应 640KiB 以上的读/写访问,以便它们访问 ROM。
当 1MiB 屏障被打破(包括或不包括HMA)时,从 640KiB 到 1MiB 的范围不能用于向后兼容。这创造了第一个洞:标准洞。
286 只有一个 24 位地址总线,因此有 16MiB 的地址空间。
与此同时,ISA 总线已经战胜了MCA 总线,并在 IBM PC 兼容硬件中取得了胜利。
一些 ISA 扩展卡带有扩展 ROM,标准孔已经用尽,在 16MiB 地址空间的末尾保留了一个 1MiB 孔。
我称这个洞为ISA 洞。
从 32 位系统转换到 64 位系统时,PCI(e) 发生了几乎相同的事情,生成PCI 孔。
除了这些漏洞之外,还有一些内存范围是可读/可写的,但会携带由 BIOS 布置的宝贵信息——即ACPI 表。
此类范围不能被操作系统随意覆盖,因此必须向其报告。
所有这一切都在e820 服务中达到顶峰,它不是返回内存大小(根据上面的讨论,这没有意义),而是返回一个由范围及其类型(可用、保留、可回收、坏、NVS)组成的内存映射.
这也反映在 GRUBmultiboot_info_t
结构字段mmap_*
中,您应该使用这些字段来代替OSDev wiki中指示的mem_lower
和。 mem_upper
1 DIMM使用rank、bank、列和行号进行访问,但内存控制器通常使这种寻址成为线性和连续的。