引子:
这是逻辑地址(虚拟地址),包括程序中打印的变量地址显示的都是逻辑地址,并不是内存空间上的物理地址。
每条指令在被执行时,读取操作数时需要给出操作数所在的内存地址,这个地址不能是物理主存地址,因为该程序在哪种硬件设置的机器上运行并不能事前确定,那操作系统就不能在此给出对应于某台机器的物理地址。
一、物理内存和虚拟内存
我们先来了解一下,什么是物理内存,什么又是虚拟内存?
1.物理内存:指通过物理内存条而获得的内存空间,主要作用是在计算机运行时为操作系统和各种程序提供临时储存。
2.虚拟内存:对内存架构(内存、缓存、硬盘)进行管理(内存管理系统)的一种手段。简单理解就是在硬盘上划分出一块区域作为内存使用。
2.1 对于用户:
计算机主要面向的是对操作系统等计算机知识几乎没有了解的普通大众,他们大多是不了解什么主存外存的,所以为了方便用户的使用,就有必要使得程序不管是位于内存架构的哪个层次,对于用户来说都是一样的。虚拟内存就是让内存管理实现媒介透明的手段。
2.2 对于主存:
众所周知,一个程序要想运行,就必须加载到物理主存(内存)中,但是物理主存的容量是非常有限的,我们当然可以选择购买更大的物理主存,可是很费钱,那么还有没有什么办法可以在不明显增加成本的基础上扩大内存容量的呢?
虚拟内存就可以做到,它的手段就是将物理主存扩大到便宜、容量大的磁盘上,即将磁盘空间也看作是主存空间的一部分。
用户程序可以存放在主存,也可以部分存放在主存、部分存放在磁盘,那么程序发出的地址到底是在哪里是由操作系统的内存管理模块负责的。
虚拟内存让用户“感觉”内存容量大大增加了,内存速度也加快了,就像魔法师一样,让观众觉得小箱子能够“装下”一只巨大的雄狮。
二、内存管理——分页内存管理
1.内存管理使用的方法
内存管理的方法有许多种,固定加载地址的、固定分区的、非固定分区的和交换内存管理,其中只有第一种固定加载地址的内存管理适用于单道编程,其余三种则适合多道编程。与此同时,它们的共同实现机制是——基址和极限。
2.交换内存管理中的机制——基址和极限
交换内存管理是这些方法中最灵活的。它使用的基址和极限机制实际上就是“将程序发出的虚拟地址加上基址得到物理地址”。
见下图:
3.交换内存管理的两大问题
3.1 空间浪费:程序不断的执行并释放的过程中,造成了内存空间中的可用空间不连续就,难以加以应用,这种现象也称为“外部碎片化”。
见下图:
3.2 程序大小受限
当程序需要更多的内存空间时,需要将其全部从物理内存中“倒出”到磁盘上,再在内存中找到更大的一片区域去存放增长了的程序,这样使得程序的增长效率低下。同时,一个程序的大小还不能超过物理内存空间的大小。
4. 解决方法——分页内存管理
4.1 分页内存管理
将虚拟内存空间和物理内存空间皆划分成大小相同的页面,例如4kb、8kb和16kb等。并将页作为内存空间的最小分配单位,一个程序的一个页面(虚拟页面)可以存放在任何一个物理页面中。
一个程序发出的虚拟地址由虚拟页面号和页内偏移值两部分组成,组成见下:
4.2 分页内存管理是如何解决交换内存管理中的两个问题的?
1.空间浪费:通过将内存空间划分成大小一样的页面,并且将其作为内存分配的基本单位,这样就避免了大量外部碎片的积累,让内存空间得到有效利用。
2.程序受限:分页内存管理下,允许一个进程的部分虚拟页面存放在物理压面(物理内存)中,另一部分存放在磁盘上,等到需要使用时再将其从磁盘中加载到物理内存中。也就是说,当程序需要额外的空间时,只需要对其分配新的页即可,这样做使得程序的增长效率较高。
4.3 虚拟地址->物理地址的转化(地址翻译)
翻译工作则是交给mmu(内存管理单元),它只对虚拟地址的页面号进行翻译,而不处理页内偏移值。
mmu为每一个程序都配备了一个页表,里面存放的是虚拟页面到物理页面的映射,如果mmu接收到了程序发出的虚拟地址,在查找相对应的物理页面号时,没有找到,那么将会通过缺页中断来将需要的虚拟页面从磁盘中加载到物理内存的页面中。
并且随着虚拟页面的进出内存,页表的内容也是不断地变化的。
4.4 页表中的具体信息
mmu为每一个程序配备的页表除了有虚拟地址到物理地址的映射(虚拟页面号到物理页面号),还有其他的与页面的管理活动有关的信息,因为mmu要依赖页表来进行与页面相关的管理活动。
例如,页表如何知道需要的虚拟页面是否在物理页面中?那么页表中就有一项信息记录的是该虚拟页面是否在当前的物理页面中——在内存否。
再说,有一些虚拟页面是受到保护的,对它的读、写和执行操作是有限制的,记录该页面的保护信息的则是——保护标识区。
等等。
可以参考下图中,页表中存储的具体内容: