了解 bootmem 的工作原理

Understanding how bootmem works

我一直在研究 OS 概念,并决定研究这些东西在 Linux 中是如何实际实现的。但是在 page_allocator 打开之前,我在理解与内存管理相关的一些事情时遇到了问题,更确切地说 bootmem 是如何工作的。我不需要它的确切工作原理,只需要了解一些事情 are/can 是如何解决的。

很明显,bootmem不能使用动态内存,这意味着必须在运行前知道他的大小,因此可以采取适当的步骤,即必须提前知道他的位图的最大大小。据我了解,这很可能通过在内核初始化期间简单地映射足够的内存来解决,如果体系结构发生变化,只需更改映射内存的大小即可。显然,可能还有很多事情要发生,但我想我已经大致了解了?然而,对我来说真正没有意义的是 NUMA 架构。在我读到的所有地方,它都说 pg_data_t 是为每个内存节点创建的。这个 pg_data 被放入一个列表中(它怎么知道列表的大小?或者特定拱门的大小是固定的?)并且为每个节点分配位图。所以,基本上,听起来它可以创建未定义数量的 pg_data,每个都有任意大小的内存位图。如何?我错过了什么?

编辑:很抱歉没有包括参考。这是bootmem代码,也可以在mm/bootmem.c中找到:http://lxr.free-electrons.com/source/mm/bootmem.c

它依赖于体系结构。在 x86 架构上,在引导过程的早期,内核确实发出 一个 BIOS 调用 - 中断向量 0x15 处陷阱的 0xe820 函数。这个 returns 内核可以用来构建它的内存表的内存映射,包括非内存(PCI 或 ISA)设备的空洞等。引导加载程序(在内核之前)将做同样的事情。

参见:Detecting Memory

在进一步研究之后,我认为它是这样工作的:基本上,所有必要的东西都是静态分配的,即通过使用预处理器 DEFINES 确保 bootmem 的某些部分(以及其他部分)内核的)代码在特定体系结构的编译代码中存在或不存在(即使代码本身是独立于体系结构的)。这些定义在 arch/ 下的体系结构相关源代码中指定(例如 arch/i386、arch/arm/ 等)。对于 NUMA 体系结构,有一个名为 MAX_NUMNODES 的定义,确保表示节点的结构列表(更具体地说,pg_data_t 结构列表)被分配为静态数组(然后被视为列表)。表示内存映射的位图显然相对较小,因为每个页面仅表示为一位,占用 KB,或者可能是 MB。无论如何,体系结构依赖 head.S 设置系统运行所需的所有必要结构(如页表)并确保将足够的物理内存映射到虚拟内存,以便这些位图可以容纳其中而不会导致页面错误(在 x86 arch 的情况下,初始 8MB 的 RAM 被映射,这对于内核和其他结构(如位图)来说已经足够了。