0
点赞
收藏
分享

微信扫一扫

计算机操作系统内存管理——页式管理


页式管理

为解决连续分配方式中难以避免的外碎片问题,操作系统引入了非连续分配管理方式,页式管理是其中应用最广泛的一种。其核心思想是将进程的逻辑地址空间和物理内存分别划分为大小固定的“页”和“页框”,进程的每个页可以分散分配到物理内存的不同页框中,无需占用连续的物理空间。这种设计既消除了外碎片(仅存在少量内碎片),又简化了内存分配逻辑,成为现代操作系统内存管理的基础。要掌握页式管理,需从分页的基本概念入手,逐步理解地址变换的实现逻辑、效率优化手段(快表)及大规模地址空间下的页表管理(二级页表)。

1. 分页存储的几个基本概念

页式管理的实现依赖于“页”“页框”“页表”三个核心概念,这三个概念共同构成了逻辑地址与物理地址的映射基础。只有先明确它们的定义和关联,才能理解后续的地址变换过程。

(1)页与页框:大小固定的“基本分配单元”
  • 页(Page):逻辑地址的划分单元
    操作系统会将进程的逻辑地址空间按照固定大小(称为“页大小”)划分为若干个相等的部分,每个部分称为一个“页”。例如,若页大小为4KB(即2¹²字节),则一个32位逻辑地址空间(4GB)可划分为4GB / 4KB = 1048576个页,每个页的编号从0开始(称为“页号”)。
    页的核心特征是“大小固定且连续”——进程的逻辑地址空间中,页与页之间是连续的(页0的结束地址是页1的起始地址),但每个页对应的物理页框可以是分散的。例如,进程的页0可能分配到物理内存的页框10,页1分配到页框25,页2分配到页框5,无需连续。
  • 页框(Page Frame):物理内存的划分单元
    与逻辑地址空间的划分相对应,操作系统会将物理内存也按照“页大小”划分为若干个大小相等的部分,每个部分称为一个“页框”(也称为“物理块”)。页框的大小与页的大小完全一致,这是页式管理的关键设计——只有大小一致,才能确保进程的一个页恰好能装入一个页框,无需调整大小。
    页框是物理内存的基本分配单元,进程申请内存时,操作系统会为进程的每个页分配一个空闲页框;进程释放内存时,操作系统回收这些页框并标记为空闲。例如,物理内存为8GB,页大小4KB,则可划分为8GB / 4KB = 2097152个页框,每个页框有唯一的编号(称为“页框号”)。
  • 页大小的选择依据
    页大小通常由操作系统在系统启动时确定(可配置,但运行中不可修改),常见的页大小有4KB、8KB、16KB等。选择页大小需平衡两个因素:
  1. 内碎片大小:页越大,内碎片(页内未被使用的空间)可能越大(如1KB的进程分配4KB页,内碎片3KB);
  2. 页表大小:页越小,进程的页数越多,记录页与页框映射关系的“页表”就越大(如4GB逻辑地址空间,4KB页对应100万页,16KB页仅对应25万页)。
    实际系统中,4KB是最常用的页大小,既避免了过大的内碎片,也不会导致页表体积失控。
(2)页表:逻辑页与物理页框的“映射目录”

由于进程的页与页框是分散映射的,操作系统需要一种机制记录“进程的哪个页对应物理内存的哪个页框”,这个机制就是“页表”。

  • 页表的本质与结构
    页表是为每个进程单独建立的“映射表”,存储在物理内存中,其核心内容是“页号”与“页框号”的对应关系。每个进程的页表包含若干个“页表项(Page Table Entry, PTE)”,一个页表项对应一个页,页表项的数量等于进程的页数。
    一个完整的页表项除了“页框号”(核心字段,用于地址转换),还包含多个辅助字段,用于内存保护、地址变换优化等,常见字段如下:
  • 状态位(Valid/Invalid Bit):标记该页是否已装入物理内存(1表示在内存,0表示不在内存,即缺页);
  • 访问位(Reference Bit):标记该页最近是否被访问过(用于页置换算法,如LRU);
  • 修改位(Dirty Bit):标记该页是否被修改过(若修改过,置换时需写回外存,未修改则直接丢弃);
  • 权限位(Permission Bit):标记该页的访问权限(如只读、读写、可执行,用于内存保护)。
  • 页表的作用
    页表是连接逻辑地址与物理地址的桥梁。当进程需要访问某个逻辑地址时,操作系统会通过页表查找该逻辑地址对应的页号,再根据页表项中的页框号,确定物理内存中的具体位置。例如,进程的页3对应页表项中的页框号为15,则该页的所有逻辑地址最终都会映射到物理内存页框15的对应位置。
2. 分页存储管理系统中的地址变换机构

有了页、页框和页表后,核心问题就变成了“如何将进程的逻辑地址转换为物理地址”。分页存储管理系统中的地址变换机构,就是负责完成这一转换的硬件与软件协同模块,其中硬件(如CPU中的地址变换电路)负责快速执行转换操作,软件(如操作系统)负责维护页表。

(1)逻辑地址的拆分:页号与页内偏移

由于页大小固定,逻辑地址可以被拆分为两个部分:页号(Page Number, PN)页内偏移(Offset)。拆分的关键是“页内偏移的位数固定”——页大小为2ⁿ字节时,页内偏移需要n位(可表示0到2ⁿ-1的地址,覆盖整个页的范围),剩余的高位则为页号。

以“32位逻辑地址、页大小4KB(2¹²字节)”为例:

  • 页内偏移需要12位(覆盖0~4095的地址,对应页内每个字节的位置);
  • 页号则为32-12=20位(可表示0~1048575的页号,对应1048576个页);
  • 逻辑地址的结构为“20位页号 + 12位页内偏移”,例如逻辑地址0x12345678(二进制为0001 0010 0011 0100 0101 0110 0111 1000),可拆分为页号0x12345(前20位)和页内偏移0x678(后12位)。

这种拆分方式的优点是“计算简单”——无需复杂的除法运算,只需通过“移位”和“与运算”即可快速得到页号和页内偏移,适合硬件快速执行。

(2)地址变换的核心流程

地址变换机构通过以下步骤将逻辑地址转换为物理地址,整个过程由硬件自动完成(无需进程干预):

  1. 拆分逻辑地址:根据页大小对应的偏移位数,将逻辑地址拆分为页号(PN)和页内偏移(Offset)。例如,32位地址、4KB页大小,拆分出20位页号和12位偏移。
  2. 检查页号合法性:操作系统会为每个进程的页表维护一个“页表长度寄存器(Page Table Limit Register, PTLR)”,存储该进程页表的总项数(即最大页号+1)。若页号≥页表长度,说明进程访问了超出自身逻辑地址空间的页,触发“越界中断”,防止非法访问。
  3. 查找页表项,获取页框号:操作系统还会维护一个“页表基址寄存器(Page Table Base Register, PTBR)”,存储该进程页表在物理内存中的起始地址。根据“页表基址 + 页号×页表项大小”,可计算出当前页对应的页表项在物理内存中的地址,进而读取该页表项。
  • 若页表项的“状态位为1”(页在内存),则提取页表项中的页框号(Page Frame Number, PFN);
  • 若状态位为0(页不在内存,缺页),则触发“缺页中断”,由操作系统将该页从外存调入物理内存,更新页表项后,重新执行地址变换。
  1. 计算物理地址:物理地址的结构为“页框号 + 页内偏移”——由于页框大小与页大小一致,页内偏移在逻辑地址和物理地址中完全相同,只需将“页框号左移偏移位数”,再与“页内偏移”相加,即可得到物理地址。
    例如,页框号为0x56789(20位),页内偏移为0x678(12位),则物理地址=0x56789 << 12 + 0x678 = 0x56789000 + 0x678 = 0x56789678。
  2. 访问物理内存:地址变换机构将计算出的物理地址发送给内存控制器,完成数据的读取或写入。

整个流程的核心是“通过页表建立页号与页框号的映射”,其中页表基址寄存器和页表长度寄存器是硬件实现地址变换的关键——它们确保了进程能准确找到自己的页表,且不会访问超出范围的页。

3. 具有快表的地址变换机构

在上述地址变换流程中,存在一个效率问题:页表存储在物理内存中,查找页表项需要一次物理内存访问;获取页框号后,访问数据还需要一次物理内存访问,即一次地址变换共需两次物理内存访问,这会显著降低CPU的执行效率。为解决这一问题,操作系统引入了“快表(Translation Lookaside Buffer, TLB)”,通过高速缓存提升地址变换速度。

(1)快表的本质:页表项的“高速缓存”

快表是集成在CPU内部的一块高速缓存,其作用是存储最近被访问过的页表项。由于CPU的访问速度远快于物理内存(快表访问时间通常为几纳秒,内存访问时间为几十到几百纳秒),若能在快表中找到所需的页表项(称为“TLB命中”),就能省去访问物理内存页表的步骤,大幅提升效率。

快表的结构与页表类似,每个快表项存储的内容与页表项一致,包括页号、页框号、状态位、访问位、修改位、权限位等。但快表的容量远小于页表(通常只有几十到几百个项),这是因为CPU内部的高速缓存空间有限,无法存储整个页表。

快表能有效提升效率的核心依据是“程序的局部性原理”——程序在一段时间内,通常只会访问少量的页(如循环执行某段代码、连续访问某段数据),这些页的页表项会被频繁访问,将它们存入快表,就能实现高命中率(一般在90%以上)。

(2)具有快表的地址变换流程

引入快表后,地址变换流程变为“先查快表,再查内存页表”,具体步骤如下:

  1. 拆分逻辑地址:与之前一致,将逻辑地址拆分为页号和页内偏移。
  2. 查找快表:地址变换机构将页号与快表中的所有页号进行比对(硬件并行比对,速度极快):
  • TLB命中:若快表中存在与当前页号匹配的项,且该页表项的状态位为1、权限符合访问要求,则直接从快表中提取页框号,跳过步骤3,直接执行步骤4(计算物理地址)。此时,一次地址变换仅需一次物理内存访问(访问数据)。
  • TLB未命中:若快表中不存在匹配的项,或匹配项的状态位为0、权限不符,则执行步骤3,访问物理内存中的页表。
  1. 查找内存页表并更新快表
  • 按照之前的流程,访问物理内存中的页表,获取页框号(若缺页则触发中断);
  • 将当前页的页表项存入快表(若快表已满,则按“最近最少使用(LRU)”等策略替换掉快表中最久未被访问的项),确保后续访问该页时能命中快表。
  1. 计算物理地址并访问数据:与之前一致,用页框号和页内偏移计算物理地址,访问物理内存。

例如,当CPU第一次访问页3时,快表中无该页的页表项(TLB未命中),需访问内存页表获取页框号15,并将页3的页表项存入快表;当CPU再次访问页3时,直接从快表中获取页框号15(TLB命中),无需访问内存页表,地址变换效率大幅提升。

4. 二级页表

当逻辑地址空间较大时(如32位逻辑地址,页大小4KB),进程的页表会变得非常庞大——32位地址对应1048576个页表项,若每个页表项占4字节,整个页表需占用1048576×4 = 4MB的物理内存,且要求这4MB内存必须连续存放。但物理内存中可能没有这么大的连续空闲空间,导致页表无法存放;即使能存放,大量连续的页表也会浪费内存。为解决“页表占用连续物理内存”的问题,操作系统引入了“二级页表”,将页表本身也进行分页,实现分散存储。

(1)二级页表的设计思路

二级页表的核心是“将原本连续的页表拆分为多个大小相等的‘页表页’(即二级页表),再通过一个‘页目录表’(即一级页表)记录这些页表页的位置”。具体来说:

  • 一级页表(页目录表):将页表的“页号”拆分为“页目录号”和“页表号”,页目录表中的每个项对应一个二级页表的基地址,即“页目录号→二级页表基址”;
  • 二级页表:每个二级页表是原页表的一部分,存储“页表号→页框号”的映射关系,且每个二级页表的大小与页大小一致(如4KB),可分散存放在物理内存的不同页框中。

以“32位逻辑地址、页大小4KB(12位偏移)”为例,原页号为20位,可将其拆分为“10位页目录号 + 10位页表号”:

  • 页目录号10位:对应页目录表有2¹⁰ = 1024个项,每个项4字节,页目录表总大小为1024×4 = 4KB(恰好一个页框大小,可连续存放);
  • 页表号10位:每个二级页表有2¹⁰ = 1024个项,每个项4字节,二级页表总大小也为4KB(一个页框大小,可分散存放);
  • 逻辑地址最终拆分为“10位页目录号 + 10位页表号 + 12位页内偏移”,共32位,覆盖整个4GB逻辑地址空间。

这种设计的优点是“页表无需连续存放”——页目录表仅占4KB(连续),每个二级页表占4KB(分散),即使物理内存中没有4MB的连续空间,也能存放完整的页表。

(2)二级页表的地址变换流程

二级页表的地址变换需要两次查找(先查页目录表,再查二级页表),具体步骤如下:

  1. 拆分逻辑地址:将32位逻辑地址拆分为“页目录号(10位)、页表号(10位)、页内偏移(12位)”。
  2. 查找页目录表,获取二级页表基址
  • 操作系统维护“页目录基址寄存器(Page Directory Base Register, PDBR)”,存储页目录表在物理内存中的基地址;
  • 计算页目录项地址:页目录基址 + 页目录号×4(每个页目录项4字节);
  • 读取页目录项:若页目录项的“有效位为1”(二级页表在内存),则提取其中的“二级页表基址”;若有效位为0(二级页表不在内存),则触发“缺页中断”,调入二级页表。
  1. 查找二级页表,获取页框号
  • 计算二级页表项地址:二级页表基址 + 页表号×4;
  • 读取二级页表项:若状态位为1(页在内存),则提取页框号;若状态位为0(页不在内存),则触发缺页中断。
  1. 计算物理地址并访问数据:将页框号左移12位,与页内偏移相加,得到物理地址,访问物理内存。

例如,逻辑地址0x12345678拆分后:页目录号0x48(10位)、页表号0xD1(10位)、页内偏移0x678(12位)。地址变换时,先通过页目录号0x48查页目录表,得到二级页表基址0x80000000;再通过页表号0xD1查该二级页表,得到页框号0x56789;最终物理地址为0x56789678,完成访问。

二级页表虽然增加了一次页表查找,但由于页目录表和二级页表都可通过快表缓存(快表可同时缓存页目录项和二级页表项),实际效率损失很小,却解决了大页表需要连续内存的问题,因此成为32位操作系统中页表管理的标准方式(如Windows、Linux的32位版本)。


举报

相关推荐

0 条评论