操作系统笔记:第四章—存储器管理
前提:认识各种存储部件
寄存器、内存、磁盘、高速缓存、磁盘缓存
主存:保存进程运行时的程序和数据
寄存器:速度最快,价格昂贵容量不大,一般以字为单位,只要存放指令一次操作的数据就够了
高速缓存
一种速度比内存快的存储设备,一般同寄存器一样集成在CPU中。存放内存的部分拷贝,把常用的数据放这里可以提高速度。
磁盘缓存
内存的一部分,将频繁使用的一部分磁盘数据信息预读入在磁盘缓存,减少磁盘读写时间。
存储器管理
容量虽不断扩充,仍不能满足现代软件和用户的需要,是一种宝贵、紧俏的资源;
多层次处理,协调CPU与存储设备的速度差距;
主要内容:
1:程序的装入和链接
2:连续分配存储管理方式
3:分页存储管理方式
4:分段存储管理方式
5:虚拟存储器、请求分页/分段、页面置换算法
1、程序的装入和链接
多道程序环境下,程序运行必须为之先建立进程。
创建进程的第一件事:将程序和数据装入内存。
程序进内存的一般过程:
1.编译compiler:编译程序:将用户源代码编译成若干个目标模块。
2.链接link:链接程序:将形成的一组目标模块,及它们需要的库函数链接在一起,形成一个完整的装入模块。
3.装入load:由装入程序将装入模块装入内存,构造PCB,形成进程,开始运行(使用物理地址)。
逻辑地址(相对地址,虚地址)
物理地址(绝对地址,实地址)
绝对装入(逻辑地址=物理地址)
编译程序生成的“目标代码”就是”装入模块”,逻辑地址直接从某个地址R处增长,装入模块直接装入内存地址R处。
静态重定位装入
重定位:把目标程序中的指令和数据的逻辑地址变成内存中的物理地址的地址
动态运行时重定位装入:
实际运行中往往会需要程序在内存中的各位置移动,即经常需要重定位到不同的物理地址上。这种运行时移动程序要求地址变换要快速,实现时一般依靠硬件地址变换机构——一个重定位寄存器。
程序装入内存时,可多次重定位到不同位置。且可以不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。
更适用于部分装入
静态链接:
装入运行前将多个目标模块及所需库函数链接成一个整体,以后不再拆开。
装入时链接:
装入内存时,边装入边链接的链接方式。
运行时链接:
对某些目标模块的链接,在执行中需要该目标模块时,才对它进行链接。
2、连续分配方式
(1)单一连续分配
内存分为系统区和用户区两部分:
系统区:仅提供给OS使用,通常放在内存低址部分
用户区:除系统区以外的全部内存空间,提供给用户使用。
最简单的一种存储管理方式,只能用于单用户、单任务的操作系统中。
优点:易于管理。
缺点:对要求内存空间少的程序,造成内存浪费;程序全部装入,很少使用的程序部分也占用内存。
(2)固定分区分配
把内存分为一些大小相等或不等的分区(partition),每个应用进程占用一个分区。操作系统占用其中一个分区。
提高:支持多个程序并发执行,适用于多道程序系统和分时系统。最早的多道程序存储管理方式。划分为几个分区,便只允许几道作业并发
具体实现:
1)如何划分分区大小
分区大小相等:只适合于多个相同程序的并发执行(处理多个类型相同的对象)。缺乏灵活性。
分区大小不等:多个小分区、适量的中等分区、少量的大分区。根据程序的大小,分配当前空闲的、适当大小的分区。
2)需要的数据结构
建立一记录相关信息的分区表(或分区链表),表项有:
| 起始位置 | 大小 | 状态 |
分区表中,表项值随着内存的分配和释放而动态改变
3)分配回收操作
也可将分区表分为两个表格:空闲分区表/占用分区表。从而减小每个表格长度。
检索算法:空闲分区表可能按不同分配算法采用不同方式对表项排序(将分区按大小排队或按分区地址高低排序)。
过程:检索空闲分区表;找出一个满足要求且尚未分配的分区,分配给请求程序;若未找到大小足够的分区,则拒绝为该用户程序分配内存。
(3)动态分区分配
分区的大小不固定:在装入程序时根据进程实际需要,动态分配内存空间,即——需要多少划分多少。
空闲分区表项:从1项到n项:内存会从初始的一个大分区不断被划分、回收从而形成内存中的多个分区。
具体实现:
1)分区分配中的数据结构
①空闲分区表:
•记录每个空闲分区的情况。
•每个空闲分区对应一个表目,包括分区序号、分区始址及分区的大小等数据项。
②空闲分区链:
•每个分区的起始部分,设置用于控制分区分配的信息,及用于链接各分区的前向指针;
•分区尾部则设置一后向指针,在分区末尾重复设置状态位和分区大小表目方便检索。
2)分区分配算法
动态分区方式,分区多、大小差异各不相同,此时把一个新作业装入内存,更需选择一个合适的分配算法,从空闲分区表/链中选出一合适分区
①首次适应算法FF
②循环首次适应算法
③最佳适应算法
④最差适应算法
⑤快速适应算法
3)分区分配操作
分配内存
找到满足需要的合适分区,划出进程需要的空间
s<=size,将整个分区分配给请求者
s> size,按请求的大小划出一块内存空间分配出去,余下部分留在空闲链中,将分配区首址返回给调用者。
回收内存
进程运行完毕释放内存时,系统根据回收区首址a,在空闲分区链(表)中找到相应插入点,根据情况修改空闲分区信息,可能会进行空闲分区的合并。
(4)动态重定位分区分配模块
用户程序在内存中移动,将空闲空间紧凑起来提高空间利用率。但必然需要地址变化,增加“重定位”工作。
动态重定位分区分配算法与动态分区分配算法基本相同,差别在于增加了紧凑的功能。
(5)内存空间管理之对换
实现进程对换,系统必须具备的功能:
对换空间的管理
进程的换出、换入操作
3、分页存储管理方式
离散分配内存:
作业规定大小划分成小份;内存也按同样大小划分成小份
作业的任一小份可分散放入内存任意未使用的小份
1)页面的概念
①物理划分块的大小= 逻辑划分的页的大小
②页面大小要适中。
2)页表的概念
为了找到被离散分配到内存中的作业,记录每个作业各页映射到哪个物理块,形成的页面映射表,简称页表。每个作业有自己的页表。
页表的作用:
页号到物理块号的地址映射,要找到作业A,关键是找到页表(PCB)根据页表找物理块。
3)地址的处理
作业相对地址在分页下不同位置的数有一定的意义结构:
页号+页内地址(即页内偏移)
关键的计算是:根据系统页面大小找到不同意义二进制位的分界线。
从地址中分析出页号后,地址映射只需要把页号改为对应物理块号,偏移不变,即可找到内存中实际位置。
4)地址变换机构
前面讲解了地址变换的原理,那么谁具体实现地址映射?——地址变换机构。
围绕页表进行工作,那么页表数据放在哪?
寄存器。一个进程有n个页,页表就需要记录n项数据,需要n个寄存器。不现实。
内存。只设置一个页表寄存器PTR(page table register)记录页表在内存中的首地址和页表长度,运行时快速定位页表。
5)引入快表——针对访问速度问题
快表的寄存器单元数量是有限的,不能装下一个进程的所有页表项。虽不能完全避免两次访问内存,但如果命中率a高还是能大幅度提高速度。
6)两级、多级页表,反置页表——针对大页表占用内存问题
①两级页表
将页表分页,并离散地将页表的各个页面分别存放在不同的物理块中
为离散分配的页表再建立一张页表,称为“外层页表”,其每个表项记录了页表页面所在的物理块号。
②多级页表
③反置页表
4、基本分段存储管理方式
1)分段系统的基本原理
程序通过分段(segmentation)划分为多个模块,每个段定义一组逻辑信息。如代码段(主程序段main,子程序段X)、数据段D、栈段S等。
分段下的相对地址:
地址结构:段号+ 段内地址
段表:记录每段实际存放的物理地址
2)段表与地址变换机构
段是连续存放在内存中。段表中针对每个“段编号”记录:“内存首地址”和“段长”
3)分页和分段的主要区别
1.大小:页大小是系统固定的,而段大小则通常不固定。分段没有内碎片,但连续存放段产生外碎片,可以通过内存紧缩来消除。相对而言分页空间利用率高。
2.逻辑地址:
分页是一维的,各个模块在链接时必须组织成同一个地址空间;
分段是二维的,各个模块在链接时可以每个段组织成一个地址空间。
3.其他:通常段比页大,因而段表比页表短,可以缩短查找时间,提高访问速度。分段模式下,还可针对不同类型采取不同的保护;按段为单位来进行共享。
4)信息共享
分段系统的突出优点:
易于实现共享
在分段系统中,实现共享十分容易,只需在每个进程的段表中为共享程序设置一个段表项。比较课本图。对同样的共享内容的管理上,很明显分段的空间管理更简单。分页的图涉及太多的页面划分和地址记录的管理。
易于实现保护:
代码的保护和其逻辑意义有关,分页的机械式划分不容易实现。
5)段页式存储管理方式
① 基本原理
将用户程序分成若干段,并为每个段赋予一个段名。
把每个段分成若干页
地址结构包括段号、段内页号和页内地址三部分
②地址变换过程
1)elf文件装入,各种信息生成并记录;
2)开始执行 读程序代码段第1条虚拟地址,开始地址映射。