一、计算机体系结构和内存层次
1、计算机体系结构
①基本硬件结构: CPU(程序执行处)、内存(放置了代码和处理的数据),设备(I/O)
②内存的层次结构: CPU的ALU(算术逻辑单元)、MMU(内存管理单元)、寄存器和cache都在CPU内部,速度快容量小,主存(物理内存)放操作系统本身和应用,通过交换/分页和磁盘交互,将永久保存的数据放到磁盘中(虚拟内存),慢而容量大,5ms寻道时间。
2、操作系统的内存管理
(1)抽象,逻辑地址空间;(2)保护,独立地址空间;(3)共享,访问相同内存;(4)虚拟化,更多的地址空间,对应用程序透明
①操作系统管理内存的不同机制:
程序重定位,分段,分页,虚拟内存,按需分页虚拟内存
②OS本身也是软件,实现高度依赖于硬件,要知道内存架构,MMU(内存管理单元,硬件组件中负责处理CPU的内存访问请求)
二、地址空间和地址生成
1、地址空间的概念:
物理地址空间是硬件支持的地址空间
E.G:内存条代表的主存,硬盘代表的磁盘 :起始地址空间0,到地址MAXsys
逻辑地址空间是一个运行的程序所具有的内存范围,一维线性
在CPU运行的进程看到的地址:起始地址空间0,到地址MAXprog(物理地址+偏移量)
二者之间的交互,映射关系,落在物理地址空间上。
2、具体过程:
C程序通过编译,汇编,链接link,载入(程序重定位)生成EXE,将逻辑地址映射到物理空间上。C程序中函数的位置(入口),变量的名字就是逻辑地址,汇编后(.o文件)起始地址为0,把变量名和函数名转为相应的从0开始的连续逻辑地址,link把多个.o合成一个,放在硬盘中,通过loader应用程序再把exe放在内存中执行,这里有分配地址空间和映射(偏移)的过程。过程与os无关,编译器和loader来完成。此时得到的仍然是逻辑地址,
接下来,物理地址生成的四个步骤
①CPU要在内存中执行指令,ALU需要知道这条指令的内容,发送请求,传参数,参数就是逻辑地址
②查表。根据CPU中的MMU(有块区域表示映射关系,如果在MMU没查到会去内存中的MAP找),查表逻辑地址->物理地址。
③找到后CPU给主存(就是内存)发请求,请求一个物理地址的内容(就是指令的内容)
④主存会通过总线把内容传给CPU,CPU执行指令。
3、地址生成时机和限制
①编译时:
假设起始地址已知;如起始地址改变,必须重新编译
②加载时:
如编译时起始位置未知,编译器需生成可重定位的代码;加载时,生成绝对地址
③执行时:
执行时代码可移动;需要地址转换(映射)硬件支持
4、操作系统的作用是在这些步骤之前建立好映射表以及地址安全检查 。
逻辑地址要检查起始地址和长度
OS设置逻辑地址的界限和基址,不对就抛出内存异常
CPU—逻辑地址—界限寄存器—–基址寄存器—物理地址—-内存
三、连续内存分配
1、动态分区分配
当程序被加载执行时,分配一个进程指定大小可变的分区(块、内存块)
分区的地址是连续的
2、动态分配策(最先匹配、最佳匹配、最差匹配)
① 最先匹配
从0地址往后查找和使用第一个可用空闲快(要比需要的空间大)。基本实现机制要求把空闲的内存块按地址排序。回收要考虑能否合并内存块。
优点:简单,易于产生更大的空闲快,向着地址空间的结尾
劣势:易产生外部碎片(随着动态分配加剧),不确定性
② 最佳适配
找比需求大但最接近需求的空闲内存块,产生尽可能小的内存碎片。原理是为了避免分配大空闲块,最小化外部碎片,要求对空闲地址快按尺寸size排序,回收要合并。
优点:当大部分分配需要小空间时使用,简单
缺点:外部碎片太小太细,不利于后续重分配。
③最差匹配
空闲分区列表按由大到小排序,使用最大的空闲快,大块拆分变小块,可以避免产生太多微小的碎片,也要排序,回收合并。
优势:分配中大型SIZE时实用
缺点:重分配慢,对大块的请求可能没得用了。
四、碎片管理
内碎片是指分配给任务的内存大小比任务所要求的大小所多出来的内存。
外碎片指分配给任务的内存之间无法利用的内存。
1、压缩式碎片整理 :紧凑(compression)
调整内存中程序运行的位置,通过拷贝尽量把程序放到一起,空出较多的空闲位置。拷贝要考虑何时去挪,不能在程序运行的时候挪,要在waiting时,和开销。
2、交换式碎片整理 :分区对换(Swapping in/out)
硬盘当做内存的备份,把waiting的程序包括数据放在磁盘上,腾出空间给其余运行的程序。(抢占waiting程序回收其内存),也要考虑开销和换哪个程序