3. 储存管理
3.1 无储存器抽象
早期计算机没有内存抽象,都采用物理地址,多道程序设计都采用多线程的方式。
也可以采用静态重定位的方式:为每个程序加上一个固定的常数。速度比较慢且容易出错
3.2一种储存器抽象:地址空间
物理地址暴露带来的严重问题:
- 如果用户程序可以寻址内存每个字节,他们很容易破换操作系统
- 使用绝对的物理地址,多道程序设计很困难
3.2.1 地址空间的概念
想要互相独立的内存空间,需要解决两个问题:保护和重定位。
更好的办法是新的内存抽象:地址空间——一个进程可用于寻址内存的一套地址集合。每个进程为程序创造了一个自己的地址空间,并且这个地址空间独立于其他进程的地址空间。
- 基址寄存器和界限寄存器
采用一种动态重定位的方式,基址寄存器和界限寄存器将程序装载到内存中继续的空闲位置且装载期间无需重定位。
程序的起始物理地址装载到基址寄存器中,程序的长度装载到界限寄存器中。每个程序在装载之前都会自动加载上基址寄存器的内容。
- 缺点是每次访问内存都需要加法和比较,如果没特殊的硬件系统会比较慢。
3.2.2 交换技术
所有进程所需要的RAM数量总和超过储存器能够支持的范围,通常由两种策略来解决这个问题:
- 交换技术(swapping)——即把一个进程完整调入内存,使该进程运行一段时间后,然后把它存回硬盘。
虚拟技术(virtual memory)——使程序在只有一部分被调入内存的情况下运行。
交换技术:
交换技术在内存空间中产生了多个空闲区(hole),通过把所有的进程尽可能向下移动,有可能将这些小的空闲区合成一大块。这既是内存紧缩(memory compaction)。- 如果程序增长该怎么办?
通常采用的方法,为程序分配内存时通常采取四段的方式,最底层的是程序段,之上是数据段,在之上是为增长预留的空间,最上面是堆栈段。这样在如果程序增长的话数据段向上增长,堆栈段向下增长。如果预留空间不够则内存重新分配。
- 如果程序增长该怎么办?
3.2.3 空闲内存管理
- 使用位图的储存管理
0表示空闲1表示占用,分配单元的大小与位图的大小成反比。但是如果需要查找连续的0串来分配内存是非常耗时的操作。这是位图的缺点。 - 使用链表的内存管理
维护一个已分配内存段和空闲内存段的链表。
- 优点是当进程终止或被换出时链表的更新非常直接。
- 为新进程分内存的算法:
- 首次适配算法-沿着段链表搜索,直到找到一个足够大的空闲区。
- 下次适配算法-记录当前搜索的区域,下次中这里搜索。速度慢于首次适配。
- 最佳适配算法-找到适应当前程序的最小程序空闲区。会产生大量的小碎片
- 最差适配算法-总是分配最大的可用空闲区。仿真表明也不是很好的算法。
- 快速适配算法-为常用大小的空闲区维护一个单独的列表,其实如果对进程内存和空闲内存分别维护可用加快上述四个算法,但同时也增加了维护的成本,快速适配可看做是这种维护的一种简化。