目录
[一 前言](#一 前言)
[二 深入理解页表](#二 深入理解页表)
[三 页表的实际组成](#三 页表的实际组成)
[四 总结](#四 总结)

一 前言
页表是我们之前在讲到Linux : 进程地址空间-CSDN博客的时候说到的,它是物理内存到进程程序地址空间的一个桥梁,通过它,物理内存的数据和代码才能映射到进程的程序地址空间中,在信号内核态和用户态这一节我们又提到了内核空间的页表,讲到了该内核级页表不同于前面说的用户级页表是每个进程都有的,内核级页表 整个系统只有一份。但是之前我们对页表的理解还都处于一个比较简单的层面,事实上页表的实现还是比较复杂的,这次我们深入理解一下页表构成及功能。
二 深入理解页表

这是我们之前所理解的简化版的页表, 我们将页表的映射功能抽象成了两栏 ,实际上页表并不只有简单的两栏,其比较复杂,且不是用一张表就可以表述出来的。
为了方便理解,我们暂且对复杂的页表结构做简单抽象,以一级页表来表示

-
RWX权限:我们知道Linux中一切皆文件,这里即我们所熟知的读、写、执行权限,表示的是进程对物理内存的访问权限 。
-
U/K权限:U表示User,K表示Kernel,即表示的用户和内核,就是在内核中的信号一篇中提到的用户态和内核态,用以区分访问内存的用户权限和内核权限。
-
是否命中:当CPU需要访问指定内存的数据的时候,会用虚拟地址通过页表向物理内存中查询数据。但是程序中的数据不是一下子全部加载到物理内存 的,即页表中可能不存在指定的物理内存,所以CPU需要访问数据的时候,可能会存在一次找不到的情况,称为未命中。
三页表的实际组成
我们以32位环境为例,即进程地址空间和物理内存最大都为4GB,如果使用一级页表(即只使用一张页表),想要将虚拟地址空间和物理地址一一对应下来,这个页表需要储存多少行条目?
如果页表的一行只表示一个地址,那么32位的计算机就有着2的32次方个地址,然而页表中的一行不止存储一个地址,还要存储是否命中,RWX权限,U/K权限,且在32位环境下地址的大小为4字节,所以页表中一行条目的大小是12个字节,要存储所有的地址的话这个页表得有多大呢?2^32 * 12 = 34,359,7,单位是字节,一共是48GB,而我们的物理内存最大才是4GB.很明显,以一级页表来将虚拟内存对应的物理内存全部映射到是不可能的。所以事实上,在操作系统中的页表是多级页表,在32位系统中,采用的是两级页表的形式。
🌃:在对二级页表做介绍之前我们先来补充一些概念:
在32位环境下,物理内存和虚拟地址空间大小都是4GB,同时在CPU访问数据时,提供的虚拟地址也就是32位的。虚拟地址和物理地址的映射需要通过页表来完成,CPU需要有能力提供覆盖 所有物理地址内存的地址,32位环境下,就是32位进制,虽然CPU给页表提供的虚拟地址是32位的,但是却不是直接将32位作为一个整体在页表中查找物理地址的。而是将32位二进制分为了 10+10+12的形式。即:
- 虚拟地址和物理地址:在32位系统中,虚拟地址和物理地址的空间都是4GB。
- 虚拟地址的处理:虽然虚拟地址是32位的,CPU在查找物理地址时并不会直接使用整个32位地址,而是将其拆分成三段。
- 地址拆分的方式:虚拟地址被分为三部分:前两部分各有10位,最后一部分有12位。这样做是为了有效地在内存中查找和映射物理地址

🚀:事实上CPU是以如下的形式查找物理内存:

可以看到在二级页表中出现了page这一起始地址,这个page又是什么呢?
🍎 :在之前我们介绍Linux的文件系统的时候,讲到操作系统的I/O操作的基本单位通常都是4KB,为了方便操作操作系统也会以4KB为单位的大小来管理内存,即操作系统会将物理内存以4KB位基本单位,并将其称为页框,也就是这里的page 。除了物理内存之外,磁盘中的程序在进行编译的时候也是按照4KB为单位划分好的。

操作系统对于程序地址空间也是按照4KB为基本单位进行管理的。
🏄 :CPU对于物理内存的查找实际如下:
-
首先使用的是虚拟地址的最高的10位,在页目录中查找到对应的页表的地址。
-
接着通过虚拟地址的中间的10位也就是页表地址----------------->查找对应的page的起始地址,这个page的起始地址其实就是个真实的物理地址,找到的就是物理内存中的一页page。
-
最后虚拟地址的最后12位起到的是一个偏移量的作用,我们称虚拟地址的最后12位为页内偏移量。而2^12=4KB,就是内存中的存储单元,根据偏移量,我们就可以在4KB内找到对应的地址。
完整流程如下:

四 总结
页表设计的优点
**节省内存:**如果使用一级页表,整个4GB的内存地址空间都需要为每个页面创建一个对应的页表项,这会占用大量内存。而使用多级页表,页目录的大小一般为KB级别,且由于第二级页表是按需创建的,因此只在需要时才分配内存。这样可以显著节省内存。最坏情况下,内存占用也只是MB级别。
**方便管理:**多级页表的结构类似于一颗多叉树。第一层页表(页目录)指向第二层页表,第二级页表就像树的节点一样,可以按需创建、删除和管理。
这种结构使得管理更加灵活和高效,尤其是当内存需求不均匀时,可以动态分配和释放内存。