因为分段采用的是将空间划分为大小不同的部分,这样的话会导致整个空间比较零碎,会给内存维护带来一定的困难。

为了解决这个问题,我们可以把内存空间分割成大小一样的片段,这种思想称为分页。

分页不是将一个进程的地址空间分割成几个不同长度的逻辑段(即代码、堆、段),而是分割成固定大小的单元,每个单元称为一页。

我们把物理内存看成是定长的一个分割过的槽,叫作页帧(page frame)。每个这样的页帧包含一个虚拟内存页。如下图:

image-20230418170854468

当分页出现以后,一个进程地址空间被引入内存就变为下图:

image-20230418171040236

为了记录地址空间的每个虚拟页放在物理内存中的位置,操作系统通常为每个进程保存一个数据结构,称为页表(page table)。

页表的主要作用是为地址空间的每个虚拟页面保存地址转换(address translation),从而让我们知道每个页在物理内存中的位置。

页表中有什么

页表中有一个有效位的标识符。该标识符用于标记对应的地址空间是否使用,如果尝试访问标记为未使用的地址空间,那么程序可能会被终止。

通过有效位,我们可以只对标识为已经使用了的地址空间进行分配物理内存,这样就节省了大量内存。

还有一个存在位,用于标识该页是在内存中还是被换出到了磁盘。

参考位用于标记该页是否被访问。

分页带来的问题

引入分页后,我们每次想要找到具体的物理地址时,系统需要先从进程的页表中取到对应的页表项,然后才能进行具体的地址空间到物理地址的转换。

在分段的设计下,我们可以直接从进程的基址寄存器中找到对应的物理位置。

而引入分页后,我们需要先从内存中取出页表,然后在页表中去找对应的地址空间到物理地址的转换。相当于多了一次取页表的操作。

而且页表需要占用物理内存。

要注意,每一个进程都会对应一个页表。每次都要从内存中找到该进程对应的页表,然后从页表中取地址的映射。

参考

《操作系统导论》