内存是操作系统的核心,程序指令只有被加载到内存中才可以被CPU调度执行。
内存,是由字
或字节队列
组成,每个字或字节队列都有它自己的地址
。
CPU,根据程序计数器
的值从内存中取指令
,可能是从指定内存地址读数据
或将数据存入
指定内存地址。
CPU与内存之间的数据交互通过系统总线
来传输。
通常来说,程序是以二进制
的形式存储在硬盘
上。只有将程序加载到内存
中,并构造成进程
的形式,才可以被真正的使用。在进程的运行过程
中,CPU从内存中获取指令和数据
,并服务于进程,而在进程使用完毕
,终止之后,将会释放
所占用的内存资源。
CPU产生的地址称为:逻辑地址,内存单元的地址称为:物理地址。
逻辑地址
,又称为:虚拟地址
,程序所产生的所有逻辑地址
形成了逻辑地址空间
。逻辑
地址空间所对应
的物理
地址形成了物理地址空间
。
有一种物理硬件设备负责将逻辑地址
和物理地址
进行映射
,这种设备称为:内存管理单元
MMU。
内存管理的核心:将逻辑地址空间绑定
到物理地址空间。
内存分配分为:连续内存分配、非连续内存分配。
连续内存分配
,包含有:多分区分配方法
、固定分区机制
。
多分区分配方法
当一个区被释放
时,就从输入队列
中取出一个进程
,将其载入空闲区
中,当该进程结束运行时,该区又可以被其它
进程使用。不过这种方法早年前已经被弃用
了。固定分区机制
在操作系统内部保留一个表
用来标识哪块内存可用
,哪块内存被占用
,当一个进程到达时,就在表中根据首先适应
、最佳适应
、最差适应
等策略为其分配一个合适的分区。如果分区过大,那么将可以被多个进程使用,如果无法使用就浪费了。当进程终止,就释放内存分区交还给系统,继续为其它进程服务。如果分区过小,可以合并使用。
以上2种方式,都存在着碎片问题
,另外,维护内存分区及移动分区的代价过高
。
非连续内存分配
,包含有:分页机制
、分段机制
。
分页机制
分页机制是一种非连续
的内存管理策略,相比连续
的内存管理策略来说,不需要再为找不到一块完整的、连续的内存而苦恼。在分页
机制中,不会产生外部碎片,因为允许不连续,每一块内存都会被利用,但会产生内部碎片。
将物理内存
分成固定大小的块,称为:帧
,将逻辑内存
也分成固定大小的块,称为:页
。程序执行的时候,页就从后备存储器装入到有效物理帧中。
CPU执行的时候,产生的地址包含:页号
、页偏移
。
逻辑内存是连续的,根据页号
、页偏移
计算得到物理内存具体位置。
在程序的内存视觉中,内存都是单调递增的。
通过页号
可以索引到页表
,页表
包含了物理内存
中每个页
的基地址
,也就是帧号
。基地址
乘以页面大小
,再加上页偏移
,就得到物理内存
的具体地址。
每个物理帧都在帧表
中存储着,包含:分配了哪些帧、哪些帧空闲、共有多少帧。
如果被分配了,那么会记录分配给了哪些进程
。
由于通过页表
这种方式计算出物理内存地址
的方式需要访问2次
内存,效率较低
,也就产生了TLB
,这是一种较小的快速查找硬件高速缓冲
,只通过页号
就可以迅速查找到帧号
。如果没有
查找到,那就通过页表
去查找。
由于现在的计算机支持的逻辑空间
较大,在2^32 ~ 2^64
之间,基于页表
这种机制,这样会导致每一个进程需要创建至少4MB
的物理空间
给页表使用。
通过两级分页算法
将页表再次分页
,分为:页号
、页表页号
、偏移量
。
利用这种方式,可以有效减少物理内存的使用量,甚至还可以使用三级分页
再次减少内存使用量。分段机制
与分页
机制不同,分段
机制采用一段一段划分的,每一段的大小可以不一样,并且可以动态伸缩。在段表
中记录的是二维地址
,包含:< 段号 - 偏移量 >
。
通过二维地址
在段表
中查找计算出具体的物理地址
。虽然,分段机制不是连续的
,但是每一段大小不一致,可能有些段过大
,暂时难以找到合适的位置,需要等待且外部碎片
会比较多。另外,通过分段
,可以针对某些段设置为只读、共享,可以有效的保护
内存段不被修改且节约
内存。