操作系统的存储管理

写在前面:我们都希望计算机拥有一个私有的,无限大的,速度无限快并且是永久性的存储器,但是这样额要求必定会价格昂贵,经过多年的探索,人们提出了“分层存储管理体系”,在这个体系中有:高速缓存(cache),内存,磁盘存储,可移动存储装置。基于这个体系,操作系统有自己的管理这个部分方法(存储管理器),它的任务就是有效管理内存。

1、无存储器抽象

最早的计算机中是不存在存储器抽象的,那么呈现在编程人员面前的就是物理内存,这种情况下同时运行两个程序是不可取的,一旦一个程序改变一个值,必定将该位置另一个程序的存的数值擦除,这样两个程序都无法正常运行。但是若想要运行多个程序应该怎么做呢?一个简单的思路就是操作系统只需要吧当前内存中所有的内容全部保存在磁盘文件上,然后把下一个程序读入内存再运行就可以了,只要保证一个时间内内存中只有一个程序运行就可以。这里不仔细讨论这种情况下式如何做的,只讨论它有什么弊端。

1)、把物理内存暴露给进程,那么用户程序很容易寻址到内存中,就很容易破坏操作系统。

2)、这种模型下想要运行多个用户程序是很困难的。

2、存储器抽象:地址空间

要想对个程序同时执行,必要条件是两个程序之间相互不受影响,要解决这个问题:保护和重定位

为了更好的实现保护和重定位,一个新的内存抽象——地址空间应运而生,地址空间内程序创建一个抽象的内存,是一个进程可用于寻址内存的一套地址集合,捏个进程都有自己的地址空间,并且是独立的。由于地址空间相互独立,所以起到保护作用,那么重定位怎么做呢?这里介绍比较旧的方法(当然现在已经有MMU)就是在CPU中配置基址寄存器和界限寄存器,分别装载程序的起始地址和程序长度。这种方法是早期intel 8088所使用。

2.1、交换技术

如果计算机的内存足够大,可以保存所有的进程,但是计算机的发展进程的大小发展速度远超过存储器的发展速度,如果一个所有进程都保存在内存里需要巨大的内存,很容易出现内存超载的情况。那么解决内存超载的有两种方法:交换技术虚拟内存

交换技术:把一个进程完整调入内存,使该进程运行一段时间,然后把它写回磁盘,空闲进程主要存在磁盘上,这样不运行时候就不占用内存。

如图,开始内存中只有进程A,之后创建进程B和C,从磁盘将他们调入内存,然后A被调出,存入磁盘,然后D被调入,B被调出,最后A再次被调入,在换入换出的过程中,通过软件或者硬件进行重定位,这里很好使用基址寄存器和界限寄存器。

交换技术在内存中产生很多空闲区,就叫做空洞,通过把所有的进程向下移动,将这些小的空闲区合并为大块,该技术称为内存紧缩,但是该技术会耗费大量的CPU时间。但是具体在换入进程时候分配多大的内存,如果进程在运行过程中占用内存大小是不变的,就很简单,找到合适的内存分配即可,但如果进程是动态的,比如一些进程会通过new或者,malloc去申请内存,那么在分配时候就可以通过将内存分段处理,例如供变量动态分配和释放的作为堆使用的一个数据段,以及存放普通局部变量与返回地址的堆栈段。对于动态分配内存,操作系统必须对其进行管理,一般有两种跟踪内存使用情况的方法,位图和空闲链表。

2.1.1、空闲内存管理

1)位图法

使用位图法时,内存可能被划分成几个字到几千个字的分配单元,每个单元对应位图中的一位,0表示空闲,1表示占用。

 2)链表的存储管理

维护一个记录已分配内存段和空闲链表的链表,其中链表中的一个节点或包含一个进程,或包含两个进程的空闲区如上图c。当按照地址顺序在链表中存放进程和空闲区时候,有几种算法可进行内存分配。分别为首次适配算法,下次适配算法,最佳适配算法,最差适配算法,快速适配算法。

2.2、虚拟内存

基本思想是每个程序拥有自己的地址空间,这个空间被分割成多个块,每一块被称作一页或页面,每一页有连续的地址范围,这些页被映射到物理内存,但并不是所有的页必须在内存中才可以执行,当程序引用到一部分在物理内存中的地址空间时,由硬件立即执行必要的映射,当程序引用到不在物理内存的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的指令。

2.2.1、分页

大部分的虚拟内存都使用分页的技术,任何计算机程序引用一组地址,地址可以通过索引,基址寄存器,段寄存器或其他方式产生,由程序产生的这些地址成为虚拟地址,它们构成一个虚拟地址空间,如果在没有虚拟内存的计算机上,系统直接将虚拟地址送到内存总线上,读写操作使用具有相同地址的物理内存字,在有虚拟内存的计算机上,系统将虚拟内存送到内存管理单元(MMU)中,MMU将虚拟地址映射为物理地址。

 那么页表到底怎么工作的呢?

上图中左侧为虚拟地址空间,右侧为物理内存地址,可以发现我们虚拟地址有64K,但是实际的物理内存地址只有32K,因此理论上可以编写64K的程序但是实际中并不能完整被装载进内存中,因此在磁盘中必须有64K的一个副本才可,保证程序片段在需要时候能背导入内存。

虚拟地址空间按照固定大小被划分,每部分成为页面,物理内存经过相同大小的划分为页框,通过建立映射就可以实现64K虚拟地址空间到32K的物理地址空间映射。在寻址过程中只需要寻找页面中的编号,通过映射关系寻找其在物理内存中的位置,如果页面被映射(在位),则直接进行寻址,如果未进行映射,那么就会产生缺页中断,操作系统通过页面置换算法将一些页面置换出,实现重新映射。检查是否在位,完成内存映射都是由MMU完成,那么它怎么完成的呢?

2.2.2、页表

MMU内部通过页号作为页表的索引,以找到对应虚拟页面的页框号,如果在位(1),将页表中的查询到的页框号复制到输出寄存器的高3位,再加上输入虚拟地址中的低12位偏移量。如此构成15位物理地址,如果不在位(0),则产生缺页中断,操作系统会重新置换页面产生新的页面,重新完成映射,按照上述构成物理地址,最终将物理地址输出到内存总线上。

 2.2.3、加速分页过程

任何分页式系统中,都需要考虑两个问题:

1)虚拟地址到物理地址转换必须要快

2)如果虚拟地址空间很大,页表也会很大,对于32位计算机若页长为4K,那么地址空间将有100万页。

核心就是减少对内存的访问,为此看一种方法:1、转换检测缓冲区(TLB)

转换检测缓冲区(TLB)基于一种现象,大多数程序总是对少数的页面进行多次访问,因此有部分表项被反复读取。因此为计算机设置一个小型的硬件设备,实现虚拟地址到物理内存的映射,而不需要访问页表,这个设备被称作转换检测缓冲区(TLB),它记录了一个页面的相关信息,包括虚拟页号,页面修改位,保护码,对应的物理页框。每次访问如果在表中直接进行转换,如果不在表中则需要去页表中查询,替换该TLB。

2.2.4、多级页表

在原来的内存页表方案之上,引入快表(TLB)可以用来加快虚拟地址到物理地址的转换,但是还有一个问题,怎么处理巨大的虚拟地址空间。下面我们看多级页表。

一个简单的例子,在32位地址空间中,被分为10位的PT1域,10位的PT2域和12位的offset域,因为偏移量是12位,所以页面长度为4KB。

 如何工作呢?上图,左为顶级页表,共有1024项,对应10位PT1域,当进行内存访问时,首先访问顶级页表的索引,因为4G(32位)地址空间被分为1024个4MB快,所以这1024个快都被表示4MB的虚拟地址空间。

由索引表项中含有的二级页表的地址和页框号找到PT2域,通过查询二级页表的索引找到虚拟页面的页框号。但是像这样也可以继续进行扩充为三级,四级等等,虽然灵活性变大,但是复杂程度也在增加。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值