第三章 内存管理
3.1 程序的装入和链接
★ 高级语言的源代码转化为进程的3个基本步骤:
编译:由编译程序(compiler)将用户源代码编译成若个目标模块
链接:由链接程序(linker)将目标模块和库函数链接,形成一个完整的装入模块
装入:由装入程序(loader)将装入模块装入内存。
★ 空间分类
名空间:编写程序时,用符号名来访问某一单元。符号名空间
逻辑空间:目标程序中,以0为基址进行编址,符号名用具体的数据代替。
内存空间:物理地址
★ 链接
含义:源程序经过编译后,可得到一组目标模块,再利用链接程序将这组目标模块与所需的库函数链接形成装入模块。
静态链接:在程序运行之前,先将各个目标模块及它们所需的库函数链接成一个完整的装配模块(又称执行模块),以后不再拆开。
装入时动态链接:目标模块在装入内存时,采用边装入边链接的链接方式。
运行时链接:对某些目标模块的链接,是在程序执行中需要该目标模块时,由操作系统去找到该模块并将之装入内存,随后把它链接到调用者模块上。
★ 装入
装入的任务:将可装入模块装入内存;地址重定位:将执行文件中的逻辑地址转化为内存物理地址的过程。
绝对装入方式:
- 在编译时就知道程序将驻留在内存中的具体位置,编译程序产生绝对地址的目标代码
- 装入模块在装入内存时,由于程序中的逻辑地址与实际内存地址完全相同,故不需对
程序和数据的地址进行修改。 - 优点:实现简单、无须进行逻辑地址到物理地址的变换。
- 缺点:程序每次必须装入同一内存区;程序员必须事先了解内存的使用情况,根据内存情况确定程序的逻辑地址;不适于多道程序系统。
可重定位(静态重定位)装入方式:
- 编译时采用相对地址,即编译器假设是装入到从零开始的内存位置。
- 逻辑地址与装入内存后的物理地址无直接关系。
- 必须重定位。静态重定位技术:地址映射在程序装入时进行,以后不再更改程序地址。
- 缺点:程序重定位后就不能移动,因而不能重新分配内存,不利于内存的有效利用;程序在存储空间中只能连续分配,不能分布在内存的不同区域;难于共享。
运行时重定位(动态重定位)装入方式:
- 程序的地址转换不是在装入时进行,而是在程序运行时动态进行。
- 运行时动态装入需要硬件支持,即重定位寄存器,用于保存程序在内存中的起始地址。
- 程序被执行时,通过重定位寄存器内的起始物理地址和指令或数据的逻辑地址计算其物理地址。
- 优点:程序不必连续存放在内存中,可分散存储,可移动;便于共享;有利于紧凑、碎片问题的解决;主流方式
- 缺点:需要硬件支持,实现复杂;同一地址,可能多次转换。
3.2 存储管理
★ 单一连续分配
- 整个内存空间分成系统区和用户区,系统区给操作系统使用,用户区给用户使用。
- 适合单用户、单任务OS
3.2.1 分区管理
分区管理适用于多道程序系统和分时系统。
固定分区
- 把内存分为大小相等或不等的分区,在每个分区中只装入一道程序。
- 分区分配算法:为进程分配某个空闲分区。
分区相等时,任选一个空闲分区;
分区不等时,根据空闲分区选择最佳任务或根据任务选择最佳空闲分区。 - 存储保护:界限寄存器
- 优点: 比单一连续分配方法,内存利用率提高了;可以支持多道程序,无外部碎片;实现简单
- 缺点: 分区的数目在系统生成时确定,限制了系统中活跃进程的数目。小作业的内部碎片可能比较大;作业必须预先能够估计自己要占用多大的内存空间
动态分区
- 根据进程的实际需要,动态地为之分配内存空间。
- 数据结构:空闲分区表、空闲分区链
- 分区分配算法:首次匹配算法,从链首开始顺序查找,按地址从低到高排列
循环匹配算法,循环查找,按地址从低到高排列
最佳匹配算法,分配满足要求且最小的空闲分区,容量小到大排列
最坏适应算法,分配满足要求且最大的空闲分区,容量大到小排列 - 存储保护:上下界寄存器方法,存放作业的结束地址和开始地址。
基址限长寄存器方法,存放作业的起始地址及作业的地址空间长度。 - 优点: 支持多道程序;管理方案相对简单,不需要更多的软、硬件开销;实现存储保护的手段比较简单
- 缺点:主存利用不够充分,存在外部碎片;无法实现多进程共享存储器的信息;无法实现主存的逻辑扩充,进程的地址空间受实际物理内存的限制。
伙伴系统
- 综合静态划分技术和动态划分技术的优点
- 分配: 进程申请大小为k的空间,系统分配一2i的空闲分区,其中,2i-1<k≤2i
[1] 查找大小为2i的空闲分区,若找到则分配;
[2] 若未找到大小为2i的空闲分区,则查找大小为2i+1的空闲分区;若找到,则将该空闲分区划分为相等的两个分区(一对伙伴),其中的一个用于分配,另一个分区加入大小为2i的空闲分区链中;
[3] 若未找到2i+1的空闲分区,则需要查找大小为2i+2的空闲分区,若找到则需要进行两次划分。第一次将其分割为大小为2i+1的两个分区,一个用于分配,另一个加入到大小为2i+1的空闲分区链中;第二次将第一次用于分配的空闲分区分割为2i的两个分区,一个用于分配,另一个加入到大小为2i的空闲分区链中。
[4] 若仍未找到2i+2的空闲分区,则继续查找2i+3的空闲分区,以此类推。 - 回收: 释放一个大小为2i的分区时,算法:
[1] 若事先不存在2i的空闲分区,则保留该分区为一个独立的空闲分区;
[2] 若事先已存在2i的空闲分区时,则将其与伙伴分区合并为大小为为2i+1的空闲分区;
[3] 若事先已存在2i+1的空闲分区时,继续合并为2i+2的空闲分区,以此类推。 - 缺点:速度快,但内存利用率不高。
3.2.2 对换
内存扩充:借助大容量辅存在逻辑上实现内存扩充,来解决内存容量不足的问题。
覆盖技术(overlay):
- 基本思想:一个程序的几个代码段或数据段,按照时间先后来占用公共的内存空间。
- 实现: - 将程序的必要部分代码和数据常驻内存;- 可选部分在其他程序模块中实现,平时存放在外存中(覆盖文件),需
要用到时才装入到内存;- 不存在调用关系的模块不必同时装入到内存,可相互覆盖。
对换技术(swapping):
- 基本思想:把内存中暂不能运行的进程或者暂不使用的程序和数据换出到外存上,以腾出足够的内存空间,把已具备运行条件的进程或进程所需要的程序和数据换入内存。
- 优点:不要求用户给出程序段之间的逻辑覆盖结构。
3.2.3 离散分配方式
★ 分页存储管理
页面:程序地址空间被划分成若干固定大小的片段,称为页面;
页框:物理内存被划分成相同大小的块,称为页框。(页面页框大小相同)
逻辑地址结构
普通分页存储系统: 逻辑地址 = 页号 + 页内偏移量(页内地址)
多级页表存储系统: 逻辑地址 = 页面页号 + 页表页内地址 + 页内偏移地址
页表:记录进程的每个页面对应的页框信息。
地址转换(普通)
① 根据逻辑地址分离出页面号和页内偏移
② 检查页面号是否非法,若非法则产生越界错误,否则继续
③ 根据页面号检索页表,获得对应的页框号
④ 检查页表的访问控制字段,确定访问是否合法
⑤ 用页框号乘以页面大小获得其对应的起始地址,并将其送入物理地址的高端。
⑥ 将页内偏移送入物理地址的低端,即形成完整的物理地址。
地址转换(两级页表)
① 通过外部页表寄存器找到外部页表首址
② 根据逻辑地址中的页表页号找到对应的页表页首地址
③ 根据页表页内地址在页表内找到对应的页表项
④ 根据页表项获得页框号
⑤ 根据页框号算出页的首址
⑥ 页首址+页内偏移地址得到形成物理地址
页表的存储:
- 页表存放在内存(主存);
- PCB保存有页表的起始地址;
- 页表寄存器存放当前运行进程的页表的起始地址;
快表:高速缓存,专门保存当前进程最近访问过的一组页表项。
分页存储优点:存在页内碎片,但碎片相对较小,内存利用率较高;实现了离散分配;无外部碎片。
缺点:需要专门的硬件支持,尤其是快表;不支持动态链接,不易实现共享。
★ 分段存储管理
以段为基本分配单位的存储管理方式。
程序的逻辑地址空间被划分为若干个段,每个段定义了一组逻辑信息;段的长度由相应的逻辑信息组的长度决定,因而各段长度不等;分段系统往往需要编译程序的支持。
逻辑地址结构
逻辑地址 = 段号 + 段内偏移量
优点:便于程序模块化设计;便于动态链接;便于保护和共享;无内部碎片。
缺点:地址转换需要硬件的支持——段表寄存器;分段的最大尺寸受到主存可用空间的限制;存在外部碎片。
★ 分页系统和分段的比较
- 页是信息的物理单位,分页的目的是实现离散分配,减少内存的外部碎片,提高内存的利用率。或者说,分页仅仅是由于系统管理的需要而不是用户的需要。段则是信息的逻辑单位,它含有一组意义相对完整的信息。分段的目的是为了能更好地满足用户的需要。
- 页的大小固定且由系统决定,由系统把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而在系统中只能有一种大小的页面;而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时,根据信息的性质来划分。
- 分页的作业地址空间是一维的,即单一的线性地址空间,程序员只需利用一个记忆符,即可表示一个地址;而分段的作业地址空间则是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。
- 分页存储管理系统不易实现“共享”和“运行时动态链接”,而分段系统易于实现实现。
★ 段页式存储管理
采用分段方法组织用户程序,采用分页方法分配和管理内存。即用户程序可以用模块化思想进行设计,一个用户程序由若干段构成。系统将内存划分成固定大小的页框,并将程序的每一段分割成若干页后装入内存执行时。
逻辑地址
逻辑地址 = 段号s + 段内页号p + 页内偏移量w
地址转换流程:
- 根据逻辑地址分离出段号、页号和页内偏移量
- 检查段号是否非法,若非法则产生越界错误,否则继续
- 根据段号检索段表,检查段表的访问控制字段,确定访问是否合法,若合法则继续,否则产生错误。
- 根据段表获取页表长度和页表始址,检查页号是否非法,若非法则产生越界错误,否则继续
- 根据页表始址和页号检索页表,获得对应的页框号。
- 用页框号乘以页面大小获得其对应的起始地址,并将其送入物理地址的高端
- 将页内偏移送入物理地址的低端,即形成完整的物理地址。
优点:离散存储;内存利用率高;便于保护和共享,支持动态链接;无外部碎片。
缺点:地址转换复杂;存在内部碎片。
3.3 虚拟存储技术
基本思想:只装入当前需要执行的部分页或段读入到内存,程序开始执行。缺页/缺段则有处理器通知操作系统将相应页/段调入内存。操作系统把暂时不使用的页/段调出保存到外存。
虚拟存储器特征:离散型、局部性、对换性、虚拟性
常用的虚拟存储技术: - 请求分页存储管理- 请求分段存储管理- 请求段页式存储管理
★ 请求分页存储管理方式
基本原理:逻辑空间划分为页面,物理空间划分为页框,页表记录,引入请求调页和页面置换功能,页面为基本单位
优点:存在页内碎片,但碎片相对较小,内存利用率较高;实现了离散分配;无外部碎片;提供了虚拟存储器,并发度高;提供了虚拟存储器,使大作业可以在较小的实际内存中运行
缺点:必须有硬件支持;不支持动态链接,不易共享;可能造成系统抖动。
页面置换算法:
- 最优置换(OPT) 换出不再访问的,如果没有则换出最久不访问的
- 先进先出置换(FIFO) 换出最早调入内存的
- 最近最久未使用(LRU)换出最长时间未被访问过的页面
- 时钟置换算法(CLOCK,Not Recently Used)
每个页面设置一个访问位,访问该页面时置1。所有页面保存在环形链表中。发生缺页中断时,首先检查表针指向页面,如果R为0,则新页面替换之;如果R为1,则清0,表针前移一个位置,重复上述过程。 - 改进型时钟置换算法
工作集:在某段时间间隔内,进程实际要访问的页面的集合。
抖动/颠簸:虚拟内存的典型问题。
- 现象:页面频繁换入出,缺页率急剧增加;内存有效存取时间加长
- 原因:多道程序度过高,每个进程分配的页框数目过少
- 预防:采取局部置换策略;在CPU调度程序中运用工作集算法;
L=S准则;挂起若干进程