虚拟内存
虚拟内存是一种计算机技术,它允许操作系统将一部分硬盘空间用作内存来使用,从而使得程序可以访问比物理内存更多的存储空间。
- 扩展内存容量: 物理内存(RAM)是有限的,而现代应用和操作系统可能需要大量的内存来运行。通过虚拟内存,即使物理内存不足,系统也可以利用硬盘空间作为额外的“内存”来满足需求。
- 提高多任务处理能力:虚拟内存使得操作系统能够同时运行更多的程序。当物理内存不足以容纳所有运行中的应用程序时,操作系统可以将暂时不使用的数据写入磁盘,为其他应用程序腾出空间。
- 内存保护和隔离:每个进程在虚拟内存中都有自己的地址空间,这有助于防止一个程序错误地访问另一个程序的数据或系统内存,从而提高了系统的安全性和稳定性。
- 内存优化:操作系统可以根据程序的实际使用情况动态调整分配给每个程序的物理内存数量。这样可以更高效地利用有限的物理内存资源,避免浪费。
分段式内存
内存分段是操作系统中一种内存管理方法,它将程序的逻辑地址空间划分为多个大小不等的段,每个段对应程序的一个逻辑部分,比如代码段、数据段、堆栈段等。
虚拟地址映射到物理地址
虚拟地址的结构
在分段机制中,虚拟地址通常由两部分组成:
- 段号(Segment Number):标识一个特定的段。
- 段内偏移量(Offset):表示在该段内的具体位置。
映射过程
-
获取段表基址:
- 操作系统为每个进程维护一个段表,段表基址通常保存在进程控制块(PCB)中。
- CPU从进程控制块中获取当前进程的段表基址。
-
索引段表:
- 使用虚拟地址中的段号作为索引,访问段表。
- 每个段表项包含以下信息:
- 段基地址(Base Address):该段在物理内存中的起始地址。
- 段长度(Length):该段的大小。
- 访问权限(Access Rights):该段的访问权限,如读、写、执行等。
-
检查访问合法性:
- 根据段表项中的访问权限,检查当前访问请求是否合法。
- 检查段内偏移量是否在段的范围内,即段内偏移量必须小于段长度。
-
计算物理地址:
- 如果访问合法且段内偏移量在有效范围内,将段内偏移量加上段基地址,得到最终的物理地址。
- 物理地址 = 段基地址 + 段内偏移量


内存分段的缺点
- 产生外部内存碎片:由于段的大小不固定,长时间运行后可能会导致物理内存中出现许多小的空闲区域,这些区域单独来看太小,无法满足新段的分配需求。这会导致内存利用率下降。分段机制本身不会产生内部碎片(因为段的大小是可变的)
- 内存交换效率低:分段机制的段往往比较大,在内存交换的时候,交换的是一个占内存空间很大的程序,因此外存的读写速度远低于内存的读写速度,这样效率比较低。
分页式内存
分页式内存管理是一种广泛使用的内存管理技术,它将虚拟地址空间和物理地址空间都划分为固定大小的块,称为页和页框(或页面帧)。这种机制通过页表来实现虚拟地址到物理地址的映射,从而简化了内存管理和提高了系统的性能。
基本概念
-
页(Page):
- 页是虚拟地址空间的基本单位,大小通常是固定的,常见的页大小有4KB、8KB、16KB等。
- 每个进程的虚拟地址空间被划分为多个页。
-
页框(Page Frame):
- 页框是物理内存的基本单位,大小与页相同。
- 物理内存被划分为多个页框,每个页框可以存储一个页的内容。
-
页表(Page Table):
- 页表是一个数据结构,用于记录虚拟地址空间中的每个页与物理地址空间中的页框之间的映射关系。
- 每个进程都有自己的页表,页表项包含页框号和一些附加信息,如访问权限、脏位、有效位等。
虚拟地址和物理地址的映射
-
虚拟地址的结构:
- 页号(Page Number):标识虚拟地址空间中的页。
- 页内偏移量(Page Offset):表示在该页内的具体位置。
-
地址转换过程:
- 获取页表基址:CPU从进程控制块(PCB)中获取当前进程的页表基址。
- 索引页表:使用虚拟地址中的页号作为索引,访问页表。
- 获取页框号:从页表项中获取对应的页框号。
- 检查访问合法性:验证请求的访问类型(读、写或执行)是否符合页表项中定义的权限。
- 计算物理地址:将页内偏移量加上页框号,得到最终的物理地址。
- 物理地址 = 页框号 × 页大小 + 页内偏移量


内存分页和内存分段的区别
- 内存分页不会产生外部内存碎片,但是有内部内存分片;内存分段不会产生内部内存碎片,但是有外部内存碎片
- 分页后,内存交换的效率相对较高,因为每次交换只需要交换部分页面即可
多级页表
单页表中页表可能过大,占用比较大的内存空间
在32位的环境下,虚拟地址空间共有4GB,假设一个页的大小是4KB (212),那么就需要大约100万(220)个页,每个「页表项」需要4个字节大小来存储,那么整个4GB空间的映射就需要有4MB的内存来存储页表。
这4MB大小的页表,看起来也不是很大。但是要知道每个进程都是有自己的虚拟地址空间的,也就说都有自己的页表。
那么,100个进程的话,就需要400MB的内存来存储页表,这是非常大的内存了。
为了解决这个问题,提出了多级页表
多级页表是一种优化单级页表的方法,旨在解决单级页表在大规模虚拟地址空间下所面临的页表过大问题。在多级页表中,页表本身也被组织成层次结构,使得页表不再是一张巨大的表格,而是分成若干小的子页表,这样就可以大大减小每个子页表的大小,进而降低对内存的需求。
工作原理
在二级页表中,虚拟地址被分为三个部分:
-
页目录索引(Page Directory Index):用于索引一级页表(页目录)。
-
页表索引(Page Table Index):用于索引二级页表。
-
页内偏移量(Page Offset):用于在页内定位具体的数据。
-
一级页表(页目录):
- 一级页表也称为页目录,每个条目指向一个二级页表的基地址。
- 页目录的大小取决于虚拟地址空间的大小和页表项的大小。
-
二级页表:
- 每个二级页表记录了一个虚拟页到物理页框的映射关系。
- 只有那些实际使用的虚拟页才会在二级页表中占用条目。
-
地址转换过程:
- 获取页目录基址:CPU从进程控制块(PCB)中获取当前进程的页目录基址。
- 索引页目录:使用虚拟地址中的页目录索引,访问页目录,找到对应的二级页表基址。
- 索引二级页表:使用虚拟地址中的页表索引,访问二级页表,找到对应的页框号。
- 计算物理地址:将页内偏移量加上页框号,得到最终的物理地址。
- 物理地址 = 页框号 × 页大小 + 页内偏移量
如何实现空间节约
-
按需分配二级页表:
- 只有当某个虚拟页被实际使用时,才会为其分配二级页表。
- 这样可以显著减少内存占用,特别是在虚拟地址空间很大的情况下。
-
减少页目录的大小:
- 页目录的大小取决于虚拟地址空间的大小和页表项的大小。
- 例如,对于一个32位的地址空间,如果页大小为4KB,页目录的大小为 2 10 2^{10} 210个条目(每个条目4字节),总共需要 ( 2 10 × 4 = 4 K B ) (2^{10} \times 4 = 4KB) (210×4=4KB) 的内存。
- 相比之下,单级页表需要 ( 2 20 × 4 = 4 M B ) (2^{20} \times 4 = 4MB) (220×4=4MB) 的内存。
快表
快表的作用是缓存最近使用的虚拟地址到物理地址的映射关系,从而减少对主存中页表的访问次数,加快地址转换速度。

快表(Translation Lookaside Buffer, TLB)是一种特殊的硬件缓存,用于加速虚拟地址到物理地址的转换过程。在现代计算机系统中,尤其是使用虚拟内存的系统中,TLB 是提高地址转换效率的关键组件。下面详细介绍快表的概念、结构和工作原理。
基本概念
-
虚拟地址与物理地址:
- 虚拟地址:应用程序使用的地址,由编译器或程序员指定。
- 物理地址:实际存在于内存中的地址,由硬件访问。
-
地址转换:
- 在虚拟内存系统中,每次内存访问都需要将虚拟地址转换为物理地址。
- 这个转换过程通常通过查找页表来完成,而页表可能存储在主存中,访问主存的速度较慢。
快表的作用
快表的作用是缓存最近使用的虚拟地址到物理地址的映射关系,从而减少对主存中页表的访问次数,加快地址转换速度。
-
TLB 的结构:
- 条目(Entry):每个条目包含一个虚拟页号(VPN)和对应的物理页号(PPN)。
- 标签(Tag):用于存储虚拟页号的一部分,以便快速查找。
- 数据(Data):存储对应的物理页号。
- 有效位(Valid Bit):表示该条目是否有效。
- 脏位(Dirty Bit):表示该页面是否被修改过(主要用于写操作)。
-
地址转换过程:
- 虚拟地址解析:CPU 生成的虚拟地址被分成虚拟页号(VPN)和页内偏移量(Offset)。
- TLB 查找:使用虚拟页号(VPN)作为索引,在 TLB 中查找对应的物理页号(PPN)。
- 命中(Hit):如果在 TLB 中找到了匹配的条目,则直接使用该物理页号和页内偏移量组合成物理地址。
- 未命中(Miss):如果在 TLB 中没有找到匹配的条目,则需要访问主存中的页表进行地址转换,并将结果缓存到 TLB 中。

缺页中断
什么是缺页
一个进程尝试访问一个不在物理内存中的虚拟页时,会产生缺页中断。操作系统会处理这个中断,将所需的页面从磁盘上的交换区(或页面文件)加载到物理内存中,从而恢复进程的正常执行。

- 在 CPU 里访问一条 Load M 指令,然后 CPU 会去找 M 所对应的页表项。
- 如果该页表项的状态位是「有效的」,那 CPU 就可以直接去访问物理内存了,如果状态位是「无效的」,则 CPU 则会发送缺页中断请求。
- 操作系统收到了缺页中断,则会执行缺页中断处理函数,先会查找该页面在磁盘中的页面的位置。
- 找到磁盘中对应的页面后,需要把该页面换入到物理内存中,但是在换入前,需要在物理内存中找空闲页,如果找到空闲页,就把页面换入到物理内存中。
- 页面从磁盘换入到物理内存完成后,则把页表项中的状态位修改为「有效的」。
- 最后,CPU 重新执行导致缺页异常的指令。
当发生缺页中断的时候,如果没有空闲页,这时候就要使用页面置换算法选择一个物理页,如果该物理页有被修改过(脏页),则把它换出到磁盘,然后把该被置换出去的页表项的状态改成「无效的」,最后把正在访问的页面装入到这个物理页中。
页表项内容
- 状态位:用于表示该页是否有效,也就是说是否在物理内存中,供程序访问时参考。
- 访问字段:用于记录该页在一段时间被访问的次数,供页面置换算法选择出页面时参考。
- 修改位:表示该页在调入内存后是否有被修改过。由于内存中的每一页都在磁盘上保留一份副本,因此,如果没有修改,在置换该页时就不需要将该页写回到磁盘上,以减少系统的开销;如果已经被修改,则将该页重写到磁盘上,以保证磁盘中所保留的始终是最新的副本。
- 硬盘地址:用于指出该页在硬盘上的地址,通常是物理块号,供调入该页时使用。
页面置换算法
页面置换算法的功能是,当出现缺页异常,需调入新页面而内存已满时,选择被置换的物理页面,也就是说选择一个物理页面换出到磁盘,然后把需要访问的页面换入到物理页。
最佳页面置换算法
最佳页面置换算法基本思路是,置换在「未来」最长时间不访问的页面。

先进先出置换算法
这是最简单的置换算法,它总是选择最早进入内存的页面进行替换。虽然实现简单,但是FIFO算法可能会导致某些经常被访问的页面被错误地换出,从而降低系统性能。

最近最少使用(LRU):
LRU算法会选择最近最长时间未被使用的页面进行替换。
效果比较好,但是开销太大,一般很少使用

时钟页面置换算法
该算法的思路是,把所有的页面都保存在一个类似钟面的「环形链表」中,一个表针指向最老的页面。
当发生缺页中断时,算法首先检查表针指向的页面:
- 如果它的访问位是0,淘汰该页面,并把新的页面插入这个位置,然后把表针前移一个位置;
- 如果访问位是1,清除访问位,并把表针前移一个位置,重复这个过程直到找到了一个访问位为0的页面为止。

最少频繁使用(LFU):
LFU算法会选择那些在最近一段时间内最少被访问的页面进行替换。这种方法依赖于对每个页面访问频率的统计。
段页式内存管理
先将程序划分为多个有逻辑意义的段,也就是前面提到的分段机制;
接着再把每个段划分为多个页,也就是对分段划分出来的连续空间,再划分固定大小的页;
这样,地址结构就由段号、段内页号和页内位移三部分组成。


1913

被折叠的 条评论
为什么被折叠?



