前言:程序储存在存储器中,执行前需通过CPU加载到内存,CPU开始执行程序并与储存器数据交互。
内存管理的目的
为多道程序运行提供良好环境,方便用户使用储存器,提高存储器利用率,实现逻辑上扩充。
存储器
主存储器(主内存/内存):
包括RAM(随机存储器),容量小速度快,临时储存程序和数据,断电丢失。
辅助存储器(辅存/通常意义的外存):
存储长期数据和程序,如所有硬盘。
高速缓存存储器(缓存):
处理器内部或紧邻处理器的储存器,读取常用数据和指令。
虚拟存储器:
内存与辅存结合的技术,通过数据交换获得更大逻辑地址空间。
内存管理的功能
内存分配回收。由操作系统完成,给程序员便利。(如进程进入内存等操作)为此,系统应记住内存空间的使用情况;实施内存的分配;回收系统或用户释放的内存空间。
地址变换。将逻辑地址转换为物理地址。
扩充内存。借助虚拟存储技术或其他自动覆盖技术,实现逻辑扩充内存。
存储保护。保证进入内存的作业在自己储存空间运行,互不干扰。
连续分配管理方式
覆盖:覆盖是一种技术,让整个程序在有限的内存空间下运行。方法是把一个程序分为多个相对独立的模块,在同一内存区域上,进行多次的加载和卸载。(更倾向于一种程序运行方式)
我们把每一个能相对独立的模块叫做覆盖段。也把每次更换的过程叫做覆盖。
单一连续分配
每一个进程需要一个连续的内存空间来运行,会产生外部碎片。
(外部碎片:内存看作整体,每个内存块中分配了不同进程,看作内部,而余留的空间就是外部。)
固定分区分配
预先定义物理内存的分区,把每个进程按大小放到分区中运行,分区一旦确定不能改变,程序通常采用静态重定位方式装入内存。产生内部碎片。
动态分区分配
作业进入主存时,根据作业大小动态建立分区,使分区正好满足作业的需要。
算法
首次适应算法(First Fit/FF)
系统按地址顺序排列的空间分区列表,每个列表都记录了起始地址和空间大小。
当进程请求,顺序查找第一个大于等于所需空间的空间,分割多余空间作为新空闲空间,更新列表。
优点:简单,效率较高,利用率较高。
缺点:会留下较小的外部碎片(分割至无法利用的空间),且列表较长时分配变慢。
循环首次适应算法(Next Fit/NF)
也叫下次适应算法。再FF的基础上把队列改为循环队列,每次从前一个开始的下一位进行查找。
优点:分布更均匀,减少查找开销。
缺点:但导致缺乏大的空闲分区。
最佳适应算法
维护一个空闲内存列表,按照内存块大小排序。进程会遍历列表,找到足够存放的最小内存块,块内空余的部分更新列表或从列表移除。
优点:减少碎片化,某些情况提高分配速度,适用性广。
缺点:算法复杂度较高,仍存在外部碎片。
最差适应算法
空闲分区按照容量大小递减的顺序排列,将满足要求的最大空间分配给作业,余留的空间更新列表再分配。
优点:最大利用大块空间,简单直观利于实现。
缺点:外部碎片,低效(大量小进程占用大内存块,分割后的空间又不能立刻分配)。
非连续分配方式
不把作业看为一个整体放入连续存储区里,把作业分化成不同的、固定大小的页,按需加载,可以有效解决外部碎片问题。
基本分页储存管理方式
等分内存
页式存储管理将内存空间划分为等长物理块(物理页面/帧),每个物理块取2的整数幂。按0开始编号,叫做物理页号。
注:1.这里的帧和帧数没有关系,按本意来更.接近“画框”。
2.通常每页大小为4k。
逻辑地址
程序的逻辑空间页划分为页面,为逻辑页面。相应分出的页号为逻辑页号/相对页号。对应的地址叫页内地址。逻辑地址由两部分组成:页号P和位移量W。
内存管理器需要的准备工作
确定程序页数
主存中留出足够空闲页面
程序的页面载入主存
分页存储管理
页号
页号(二进制)X位,每个作业最多2的X幂页。页内位移量的位数表示页大小,若页内位移量(二进制)y位,则页大小为000000000000~2的y次方。
给出逻辑地址A,页大小L。
页号P=INT[A/L],页内地址W=A MOD L(取余)
内存分配
连续的页在内存不一定连续,分块加载的页,尺寸为2的整数次幂,所以相对地址中高位部分为页号,低位为页的地址。
页表
分页系统中,进程每一页离散地储存在内存中,为了找到某页对应的帧,建立了一个页表,将页号和帧对应,如图
地址变换
程序的使用虚拟地址进行内存访问,通过其找到页表项,(页表项包含帧号或物理页地址)通过页表项内信息找到最终物理地址,以该地址访问物理内存的数据或指令。
图中,
页号:8203/4096=2
页内偏移:8203%4096=11
物理地址:物理块号*页面大小+页内偏移=28683
快表地址变换机构
CPU存取一个数据要访问内存两次,为提高地址变换速度,增设一个有并行查询能力的特殊高速缓存存储器,叫联想存储器/快表,存放页表项。
分页存储的优缺点
优点:利用率、离散分配、利于存储访问、无外部碎片
缺点:硬件支持,特别是快表、内存访问效率下降、难以共享、内部碎片
注:分段更适合编程、信息共享和保护。
分段储存管理
思想
页分割了进程,优点和缺点都在于分割的过细。当一个程序的一些页在帧时,另一些页却可能在辅存,这样不利于编程的独立性,对换入换出、储存和共享都造成了麻烦。
而划分出一种可寻址的储存空间的方法--分段,解决了这个问题。它是按照程序的自然分界划分的,且长度可动态更改。通常我们把子程序、操作数、常数这些不同类型的分到不同段,当然每个类型也可以有多个。
这样程序即完整,又能离散分配。
分段地址结构
每个段从0编址直到段结束,是一段连续的地址空间,储存一组逻辑信息。段的虚拟到实存需要段表。
一个段表项对应一个段,段表项里管理了存储段描述符(一个结构体)和段选择器(管理描述符)以及段描述符指针。
描述符包括段起始地址,长度、访问权限、是否共享等。
地址变换
按段号访问相应表项,若有效位为1,比较段内地址和段长,超出证明不在段内,地址越界中断;否则计算得到物理地址,若其内为空,缺页中断。
绝对地址(物理地址)=段基址(段起址)+段内地址
分段存储方式的优缺点
优点:
分段对程序员来说是可见的,段的逻辑独立性强,易编译、管理、维护、保护,以及多程序共享。
允许自由调度段长,利用主存。
分段共享、保护,动态链接、增长。
缺点:
主存分配麻烦
外部碎片,需拼接技术
必须通过段基址和段内地址计算物理地址,需要更多硬件支持。
分页与分段的区别
单位上:分页,逻辑单位;
分段,物理单位。
目的:分页,管理系统所需,提高内存利用。
分段,满足客户需求。
大小:页,系统决定,固定大小;
段,情况决定,长度不定。
作业地址空间:页,一维;
段,二位。
内存碎片:页,内部碎片;
段,外部碎片。
段页式存储管理方式
基本思想
把优点结合,按程序的地址空间分段管理程序(虚拟储存器),再把段按帧分页。
注:余出地址按填充/溢出方法解决。
填充:补满一页。
溢出:单段溢出的,一段的溢出页空余部分空余;多端溢出的,可能将多段的溢出共放到一个页中,以链表形式加载。
地址结构
若段号S;页号P;页内地址d
地址寄存器
按照以往的规律就好。
按作业建立段表、按每段建立页表、按页对应帧。
地址变换
慢速地址转换过程
结合上文两者的查询方法,若一个基地址为x、段号s、页号p、页内地址d
则物理地址((x+s)+p)*2^(11)+d,“*2^(11)”是一个左移操作,目的是计算帧在物理地址中的偏移量,因为一页的大小为2^12=4096,左移11位。
快速地址转换过程
多个寄存器构成一个高速缓存:快表(TLB)。快表中存放一系列映射关系(虚拟地址到物理地址),由MMU(内存管理单元)先搜索TLB,若找到(命中)则直接取用,未命中则更新TLB。
段页式存储的优缺点
优点:
可以离散储存,降低碎片量;
虚拟储存器,提高主存利用率,可多道程序运行。
缺点:
硬件支持;
某些条件会发生系统抖动(系统因为频繁页面置换而导致效率极具下降,此时CPU大部分时间都在等待磁盘IO操作);(导致原因:内存碎片、页表制作、页面更换)
程序最后一页可能存在未利用空间。
页面置换算法
当程序的部分页未加载在内存中,此时程序会出现缺页中断,就要考虑换出内存页,去运行未加载页。而换出的方法就是页面置换。
最佳置换算法(OPT)
找到未来迟迟不能运行的页,这个页是运行时最后一个需要的,把这个优先级最低的置换成现在需要的页。
缺点:无法实现。这是一个参考,可以对其他算法的性能比较。
先进先出算法(FIFO)
先进入的先退出,类似队列。
只有在线性访问下才最理想,否则若有经常访问的页,还是会因为进入时间久而退出。
而且在在少数情况下,内存块增加时,由于替换频率增加,反而会加大缺页中断率。
最少最近使用算法(LRU)
寻找最近时间内最久未使用的页进行替换,实现方法类似栈,最近使用的页被放到栈顶,每次替换时替换栈底的页,当然其他结构也可以实现。
时钟置换算法(CLOCK)
可以看作近似LRU的算法,但实现方式是在每个页加“使用位”和指针,建立循环队列,使用位每访问一次初始值为1,每指针检测一次减1,到0时再检测则置换,否则再进行循环检测。
这种方法不用排序,但性能却可能下降,而且使用位的增加也是内存开销。
最不常用算法(LFU)
找到使用频率最低的进行替换,把每个页的访问计数,可以通过移位寄存器来减少计数大小。
LRU与LFU的算法相似,可用一套硬件完成,但LFU精度有限,且无法应对频率差过大的情况。
注:若替换页面与被替换页面相同则不进行替换。