基本内存管理的简单介绍
前言:
操作系统的两个角色:魔术师和管理者。在管理者这个角度,除了CPU之外,内存是操作系统管理的另一个重要的资源。
内存管理出现的前景:当初在操作系统出现以前,成不并不需要加载到内存上运行,程序存放在卡片上,计算机每读一张卡片,就运行一条指令,程序直接从卡片到执行。但是这种做法效率极低,且灵活性很差。因此人们发明了内存存储器将需要运行的程序现行加载,在自动执行,从而提高效率和灵活性。从而出现了内存这一概念。
内存构架:
缓存的特点:低容量(相对于主存),高速度,高价格
主存(通常说的内存):中容量,中价格,中速度
磁盘:大容量,低速度,低成本的储存媒介。
内存管理:就是对内存框架进行管理,使得程序在内存框架上的任何一个储存层次上的存放对于用户来说都是一样的。
内存管理的目标:
①:地址保护:一个进程不能随便访问另一个进程的地址空间。
多道程序同时存放在内存中,操作系统要保证他们互不干扰:即一个进程不能随便访问另一个进程 的地址空间
②:地址独立:程序发出的地址应该与物理主存无关。
程序指令在执行前被加载到内存中,然后从内存中读出执行,每条指令在执行时都需要读取操作数和写入运算结果。而读取操作数就需要给出操作数所在的内存地址,这个地址不能是物理内存地址。因为不同的硬件设备有不同的物理内存,所以操作系统不能(对症下药)给出明确的物理地址。所以这里的地址必须是程序空间的 虚拟地址。
虚拟内存
出现原因:一个程序需要运行必须先加载到物理主存上,但是我们知道物理主存的容量非常有限。并且其还限制了多道编程的发展。那么如何解决这个问题呢?那就是如何能把这个内存扩充一下,那就是虚拟内存。
虚拟内存:是操作系统提供给用户的一个“幻象”,给用户提供一个比物理主存空间大许多的地址空间。
虚拟内存的中心思想:将物理主存扩大到便宜,大容量的磁盘上,即将磁盘空间作为主存空间的一部分。
操作系统在内存中的位置
现代的多数操作系统都是:在ROM里面包含了操作系统的一部分和I/O,RAM里面则包括操作系统的其他部分和用户程序。
多道编程的内存管理
1.单道编程的内存管理:将整个程序加载到内存的同一个地址上,用户程序永远在同一个地方开始执行,那么在程序运行前就可以计算出所有的物理地址。这种在运行前即将物理地址计算好的方式叫做静态链接地址翻译。
2.多道编程的内存管理:多道是有限度的!虽然多道可以改善CPU 很内存的效率,多道编程就无法将程序总是加载到固定的内存地址上,也就是无法静态链接地址翻译。那么我们就必须在运行时进行地址翻译。这种翻译叫做动态地址翻译。
3.多道编程的内存管理有两种策略:固定分区 和 非固定分区。
一:固定分区
故名思议就是将内存分为固定的几个区域,每个区域的大小固定(可一样可不一样)。最下面的分区为操作系统所占用,其他的为用户占用。
二:地址翻译
用户程序进行分区,并且在多道环境编程的环境下,程序加载到内存上的地址是不固定的,所以我们必须对地址进行翻译。
程序里面的虚拟地址只要加上去所占区域的起始地址,即可获得物理地址。即:物理地址=虚拟地址(偏移)+起始地址。由于多个程序在内存空间,所以我们还要进行地址保护 :程序所在区域的起始地址《=有效地址《=起始地址+程序长度。这两个端值分别是基址和极限,又两个基址寄存器和极限寄存器存放。
三:非固定分区
固定分区的缺点:①程序大小和分区大小的不匹配问题②僵硬:最大分区仍然小于程序需要的空间③地址空间动态增长,如果程序在运行时内存需要增长怎么办?
非固定分区:除了划分给操作系统的内存空间之外,所有的都作为一个整体,当程序需要占用内存时,就分配给他一个大小刚好的空间。
劣势一:图11-11中每个程序像罗汉一样堆叠在一起,程序需要的空间如果需要增长怎么办?
解决:中间图片给出预留的增长空间
劣势二:对于给出的解决方案一:空间的增长是对于指令和数据的空间而言,当这两个空间在允许地之内是同方向增长,那么会 出现一个问题就是不论是数据还是指令当他们增长到他们的地址上限的时间,他们在无法增长,即使在增长线之下还有空间, 也 没办法向下增长。
解决:指令(栈)和代码我们使用反方向的增长方式。Linux(OS)采取这种测咯。Windows则给栈的增长设置了边界,一旦超 过会发生报错。
交换分区:
针对上述解决。那么又有几个问题?1.操作系统怎么知道该给每个程序分配多少空间?2.怎么会知道这个进程会有多少个嵌套调 用?会产生多少新的数据?针对这个问题,可以给程序一个很大的空间,这样无形间就会造成空间浪费。
解决方案:交换分区:磁盘上的一块相当于内存的空间。
交换:将一个进程从内存倒到磁盘上,再将其从磁盘上加载到内存中的过程。
目的:1.防止程序因空间不够而崩溃。2.便于实现进程切换,程序中的许多进程并不是同时进行的。
过程:交换和非固定分区一样,每个程序占用一片连续的空间,OS仍然使用基址和极限地址来管理,在程序发生交换的过程中,虽然这两者会发生改变,但是只需要每次加载程序的时间将基址寄存器和极限寄存器的内容进行重载即可。
重叠:(了解)
如果一个程序超过了物理内存,还能运行吗?答案是能!
这个办法就是重叠(Overlay),将程序按功能划分为几个相对完整的单元,当执行完一个单元后,在执行下一个单元,并且执行完的单元将不在执行,然后我们将该单元用没执行的要执行的单元进行覆盖!
双基址:
如果我们要运行两个相同的程序,只是数据不一样,那么我们可不可以进行指令的共享?可以!那么我们怎么使在共享的过程中不产生错误呢?那就是双基址:给指令和数据各自配置基址!