[Linux 0.11] Draft 5 虚拟内存管理(mm/memory.c)
Overview 本文介绍 32 位保护模式下的内存分页, 以及 linux0.11 对物理内存的管理。 意义 既然要使用内存分页,那么就一定有他的优势所在。我们首先来探讨一下使用内存分页的意义, 分页在于为进程提供了虚拟地址空间,通过提供的这个虚拟地址空间,我们可以做到下面的这些: 精细的权限控制粒度: 内存页大小以 4KB 为一页单位(也可以是4MB, 这里不讨论这种情况), 可以针对每一个内存页设置该4K空间的访问权限。相比分段的粗粒度精细了很多,目前的分段功能只是一个兼容性考虑,分段都是将整个0 – 最大内存空间直接映射为一个段; 可以使得进程独享地址空间: 通过切换CR3寄存器的内容,可以实现多个进程占用同一个虚拟地址空间。 有效的解决了进程对大块连续内存的请求: 这里用一个例子来说明一下。 例子是这样的: 如果我们有16MB的物理内存,现在有进程A B C分别占用5MB, 2MB, 3MB内存, 且不共享内存。然后现在进程B退出了,我们还剩余8MB内存,可是如果不使用分页的话,内存连续分配, 我们现在没有办法分配出一个连续的8MB的空间了,只能分配最多最多6MB连续的内存空间, 如下图所示。 而现在存在分页,虚拟地址,我们完全可以分配连续的8MB的虚拟地址空间,其中2MB映射到物理内存的中间那个2MB空隙,其余6MB映射到最后剩余的6MB。 由此可见,分页是十分必要的,那么下面就来介绍一下如何实现分页&虚拟内存管理 地址转换过程 我们先来看一下虚拟地址是如何转换为物理地址的 完整的转换过程为 虚拟地址 –> (GDT) –> 线性地址 –> (Page Table) –> 物理地址 关于VirtualAddr -> LinearAddr 的过程我在之前的文章中有过介绍,这里就不做说明,想要跳过那个文章的读者可以简单的理解为目前的虚拟地址和线性地址值是相同的,因而我们直接从线性地址出发。首先来看下图 (图片来源:Intel® 64 and IA-32 Architectures Software Developer’s Manual) 线性地址为32位的地址, 其中高十位为 Page Directory,中间十位为 Page Table,最后十二位是 Offset。过程如下: 根据 CR3 寄存器(忘记了寄存器的功能的话戳这里)找到了页目录表的地址。 根据 Linear Address 的高十位与页表目录地址相加,找到了对应的页目录项(PDE)。 页目录项内存有该页目录的起始地址,将此地址与 Linear Address 21 – 12 位(即中间十位)相加,找到对应的页表项(PTE)…