页表、物理地址、逻辑地址、页面置换算法

页表:

  虚拟内存的概念。操作系统虚拟内存到物理内存的映射,被称为页表

  不可能每一个虚拟内存的Byte都对应到物理内存的地址,因为这样的页表非常大,于是引入 页(Page)概念,进行分页,减小虚拟内存页对应物理内存页映射表的大小。

  缺页异常:malloc和mmap函数分配内存是仅建立了 进程虚拟地址空间,并没有分配虚拟内存对应的物理内存,进程访问没有建立映射关系的虚拟内存时,处理器自动触发 缺页异常,引发缺页中断。

  缺页中断:缺页异常后产生一个缺页中断,操作系统根据页表中的   外存地址  在外村中找到所缺的一页,将其调入 内存。

  在进行动态内存分配的时,(C++ 中 new),操作系统会在硬盘中创建或申请一段虚拟内存空间,并更新到页表(分配一个页表条目),该条目指向硬盘上新创建的虚拟页,产生映射关系。

逻辑地址转线性地址:段起始地址(基地址) + 段内偏移地址 = 线性地址

  例如一个存储器大小是  1KB(8位)可以分为4段,第一段地址范围是0~255,段地址为0;;;第四段地址范围是768~1023,段地址为768;偏移地址为0~255之间。

  线性地址是一个32位的无符号整数,可以用来表达4GB的地址,高达4294967296个内存单元。十六进制表示(0x00000000~0xffffffff)

  分页机制:

    4KB分页大小,线性地址的高10位为页目录项在页表中的编号,中间10位为页表中的页号,低12位是偏移地址。

    4MB分页大小,高10位页号,低22位偏移地址。 

  1、分页单元中,页目录是唯一的,它的地址放在CPU的cr3寄存器中,是进行地址转换的开始点。
  2、每一个活动的进程,因为都有其独立的对应的虚似内存(页目录也是唯一的),那么它也对应了一个独立的页目录地址。——运行一个进程,需要将它的页目录地址放到cr3寄存器中。
  3、每一个32位的线性地址被划分为三部份,面目录索引(10位):页表索引(10位):偏移(12位)
依据以下步骤进行转换:
  1、从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);
  2、根据线性地址前十位,在数组中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不再是页的地址,而是一个页表的地址。(又引入了一个数组),页的地址被放到页表中去了。
  3、根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址;
  4、将页的起始地址与线性地址中最后12位相加,得到最终我们想要的物理地址;

线性地址转物理地址:页目录地址 + 页目录索引 = 页表地址      -----      页表地址 + 页表索引 = 页地址     ------    页地址 + 页内偏移 = 物理地址

页表计算:

  例:若页面大小L为1K(1024)字节页号2对应的内存块号b=8,将逻辑地址A=2500转换为物理地址E。 等价描述:某系统按字节寻址,逻辑地址结构中,页内偏移量占10位(说明一个页面的大小为2^10B = 1KB),页号2对应的内存块号 b=8,将逻辑地址A=2500转换为物理地址E。  

  ①计算页号、页内偏移量 页号P=A/L = 2500/1024 = 2; 页内偏移量W= A%L = 2500%1024 = 452

  ②根据题中条件可知,页号2没有越界,其存放的内存块号b=8

  ③物理地址E=b*L+W=8 * 1024+ 425 = 8644

  在分页存储管理(页式管理)的系统中,只要确定了每个页面的大小,逻辑地址结构就确定了。因此,页式管理中地址是一维的。即,只要给出一个逻辑地址,系统就可以自动地算出页号、页内偏移量两个部分,并不需要显式地告诉系统这个逻辑地址中,页内偏移量占多少位。

页面置换算法:

1.最佳置换法(OPT,Optimal): 性能好但无法实现

  🔴每次选择淘汰的页面将是以后永不使用,或者在最长时间内不再被访问的页面,这样可以保证最低的缺页率。

2.最近最久未使用置换算法(LRU):性能好但需要硬件支持,实现困难

  🔴 LRU(Least recently used):每次淘汰的页面是最近最久未使用的页面

  实现:赋予每个页面对应的页表项中,用访问字段记录该页面自上次被访问以来所经历的时间t  (需要硬件支持(寄存器、栈),性能好但实现困难,开销大)

  当需要淘汰一个页面时,选择现有页面t  值最大的,即最近最久未使用的页面。

 3.先进先出置换算法(FIFO):简单、效率低

  🔴 每次选择淘汰的页面是最早进入内存的页面

  🔴 Belady异常一:当为进程分配的物理块数增大时,缺页次数不减反增的异常现象。

  只有FIFO算法会产生Belady异常,且先进入的页面也有可能经常被访问,算法性能差。

4.时钟置换算法(CLOCK)或最近未使用算法(NRU,Not Recently Used):

  🔴 循环扫描缓冲区像时钟一样转动;

  简单实现:为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列,当某页被访问时,访问位  置为 1

  当需要淘汰一个页面时,只需要检查页的访问位,如果为 0,就选择将该页换出;如果是1,将其置为0,暂不换出,检查下一个页面;

  若第一轮扫描完全是1,则将这些页面的访问位依次置为0后,在进行第二轮扫描    -    选择一个淘汰页面最多会经过两轮扫描;

5.改进型的时钟置换算法:

  🔴 如果淘汰的页面没有被修改过,就不需要执行 I/O 操作写回外存,只有被淘汰的页面被修改过时,才需要写回外存;

  🔴 因此除了考虑页面有无被访问,还应考虑有无被修改过,其他条件相同时,优先淘汰没有修改过的页面,避免 I/O操作, 修改位 = 0(没有被修改); = 1(被修改过)

  🔴(访问位 Access,修改位 Modify);将所有可能被置换的页面排成一个循环队列;

          

  🔴 一轮:找到第一个(A = 0,M = 0)替换;不修改任何标志位;

  🔴 二轮:找到第一个(A = 0,M = 1)替换;同时将扫描过的访问位 A  置为 0;

  🔴 三轮:找到第一个(A = 0,M = 0)替换;不修改标志位;

  🔴 四轮:找到第一个(A = 0,M = 1)替换;

  🔴 第二轮会将所有访问位置为 0    -    选择一个淘汰页面最多会进行四轮扫描;

算法规则优缺点
OPT 优先淘汰最长时间内不会被访问的页面 缺页率最小,性能最好,但无法实现
FIFO 优先淘汰最先进入内存的页面 实现简单,性能差,可能出现Belady异常
LRU 优先淘汰最近最久没访问的页面 性能很好;但需要硬件支持,算法开销大
CLOCK (NRU) 循环扫描,第一轮淘汰访问位=0的,并将扫描过的页面访问位改为1。若第一轮没选中,则进行第二轮扫描。 算法开销小;但未考虑页面是否被修改
改进型CLOCK (改进型NRU) 好! 算法开销较小,性能也不错

posted on   廿陆  阅读(894)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示