如何启用分页
Linux 进程使用的分页机制包括两个阶段:
●在启动时,系统为 8 MB 的物理内存设置页表。
●然后,第二个阶段完成对其余物理地址的映射。
在启动阶段,startup_32() 调用负责对分页机制进行初始化。这是在 arch/i386/kernel/head.S 文件中实现的。这 8 MB 的映射发生在 PAGE_OFFSET 之上的地址中。这种初始化是通过一个静态定义的编译时数组 (swapper_pg_dir) 开始的。在编译时它被放到一个特定的地址(0x00101000)。
这种操作为在代码中静态定义的两个页 —— pg0 和 pg1 —— 建立页表。这些页框的大小默认为 4 KB,除非我们设置了页大小扩展位(有关 PSE 的更多内容,请参阅 扩展分页一节)。这个全局数组所指向的数据地址存储在 cr3 寄存器中,我认为这是为 Linux 进程设置分页单元的第一阶段。其余的页项是在第二阶段中完成的。
第二阶段由方法调用 paging_init() 来完成。 在 32 位的 x86 架构上,RAM 映射到 PAGE_OFFSET 和由 4GB 上限 (0xFFFFFFFF) 表示的地址之间。这意味着大约有 1 GB 的 RAM 可以在 Linux 启动时进行映射,这种操作是默认进行的。然而,如果有人设置了 HIGHMEM_CONFIG,那么就可以将超过 1 GB 的内存映射到内核上 —— 切记这是一种临时的安排。可以通过调用 kmap() 实现。
物理内存区域
我已经向您展示了(32 位架构上的) Linux 内核按照 3:1 的比率来划分虚拟内存:3 GB 的虚拟内存用于用户空间,1 GB 的内存用于内核空间。内核代码及其数据结构都必须位于这 1 GB 的地址空间中,但是对于此地址空间而言,更大的消费者是物理地址的虚拟映射。
之所以出现这种问题,是因为若一段内存没有映射到自己的地址空间中,那么内核就不能操作这段内存。因此,内核可以处理的最大内存总量就是可以映射到内核的虚拟地址空间减去需要映射到内核代码本身上的空间。结果,一个基于 x86 的 Linux 系统最大可以使用略低于 1 GB 的物理内存。
为了迎合大量用户的需要,支持更多内存、提高性能,并建立一种独立于架构的内存描述方法,Linux 内存模型就必须进行改进。为了实现这些目标,新模型将内存划分成分配给每个 CPU 的空间。每个空间都称为一个节点;每个节点都被划分成一些 区域。区域(表示内存中的范围)可以进一步划分为以下类型:
ZONE_DMA(0-16 MB):包含 ISA/PCI 设备需要的低端物理内存区域中的内存范围。
ZONE_NORMAL(16-896 MB):由内核直接映射到高端范围的物理内存的内存范围。所有的内核操作都只能使用这个内存区域来进行,因此这是对性能至关重要的区域。
ZONE_HIGHMEM(896 MB 以及更高的内存):系统中内核不能映像到的其他可用内存。
节点的概念在内核中是使用 struct pglist_data 结构来实现的。区域是使用 struct zone_struct 结构来描述的。物理页框是使用 struct Page 结构来表示的,所有这些 Struct 都保存在全局结构数组 struct mem_map 中,这个数组存储在 NORMAL_ZONE 的开头。节点、区域和页框之间的基本关系如图 9 所示。

| 论坛热门帖子: | [lch203] 写得蛮好的linux学习笔记(10-21) [黑马制造] 学习java的30个目标(10-19) [笑傲股林] 做测试半年了,有点迷茫,应该再学些什么提高自己的测试水平和测试能力呢?(10-19) [udp8589] 大家用google的来吱一声? 用百度的~~也来报道下?(10-18) [沂偌掳兆] 本人总结的一些认为C++比较经典的书籍,希望对大家有用(10-18) |
| TAG标签: | 模型 管理 内存 操作系统 探索 内核 映射 地址 使用 区域 |
注册
个人空间
