文章目录
- @[toc]
- 一、存储管理的功能
- 1.1 存储分配
- 1.2 存储共享
- 1.3 存储保护
- 1.4 存储扩充
- 1.5 地址映射
- 二、内存资源管理
- 2.1 内存分区
- 2.1.1 静态分区与动态分区
- 2.1.2 等长分区与异长分区
- 2.2 内存分配
- 2.2.1 静态等长分区的分配
- 2.2.2 *动态异长分区的分配
- 2.3 碎片与紧凑
- 三、界地址存储管理
- 3.1 基本原理
- 3.2 双对界
- 3.3 交换与重定位
- 3.4 覆盖技术
- 四、页式存储管理
- 4.1 基本原理
- 4.2 多级页表
- 4.3 反置页表
- 五、段式存储管理
- 5.1 基本原理
- 5.2 段的保护与共享
- 六、段页式存储管理
- 6.1 基本原理
文章目录
- @[toc]
- 一、存储管理的功能
- 1.1 存储分配
- 1.2 存储共享
- 1.3 存储保护
- 1.4 存储扩充
- 1.5 地址映射
- 二、内存资源管理
- 2.1 内存分区
- 2.1.1 静态分区与动态分区
- 2.1.2 等长分区与异长分区
- 2.2 内存分配
- 2.2.1 静态等长分区的分配
- 2.2.2 *动态异长分区的分配
- 2.3 碎片与紧凑
- 三、界地址存储管理
- 3.1 基本原理
- 3.2 双对界
- 3.3 交换与重定位
- 3.4 覆盖技术
- 四、页式存储管理
- 4.1 基本原理
- 4.2 多级页表
- 4.3 反置页表
- 五、段式存储管理
- 5.1 基本原理
- 5.2 段的保护与共享
- 六、段页式存储管理
- 6.1 基本原理
一、存储管理的功能
存储管理:
- 内存资源的管理
- 分级存储体系的外村资源的管理
需实现功能:存储分配、存储共享、存储保护、存储扩充、地址映射。下面只是简述,后面会细聊
1.1 存储分配
OS真忙:
作业进入内存 -> OS将其变为进程 -> 分配存储空间 -> 进程结束 -> 回收存储空间
如果是虚拟存储管理的OS:
一部分进程在内存,一部分被暂时调入外存
如果外存部分被调入内存,则回收外存空间,分配内存空间
如果内存部分调入外存,则回收内存空间,分配外存空间
文字背后需要实现的逻辑:OJ怎么记录哪些内/外存空间分配,哪些空闲?那么多可用空间用哪个?当要回收时如何回收?
我们后面会进行讨论。
1.2 存储共享
存储共享是指两个或者多个进程共用内存中的相同区域,即它们的物理空间有相交的部分。
1、存储共享的目的
- 节省内存空间
- OJ的判题机对于多用户的提交显然不可能为每个用户保存一个某语言的解释/编译程序,一是空间开销大,二是没必要,我们让其排队装入程序就行。那么每个用户进程显然都能访问存放编译/解释程序的内存空间。
- 实现进程间通信
- 如读者、写者问题,它们就是公用同一块区域来实现进程间的通信。
2、存储共享的内容
- 代码共享
- 数据共享
1.3 存储保护
这个很好理解,我们为使得OS正常运行自然要对内存加以保护。
一般包括如下内容:
- 防止地址越界
- 防止操作越权
1.4 存储扩充
Genshin Impact 的大小已经来到几十G了,可我们在8G内存的PC端或PE端仍能顺利运行是为何呢?
这就是操作系统的虚拟性,内存快贵小,外存慢廉大,要用到的就调入内存,暂时用不到的调入外存,要用时从外存调。
我们玩一些3A大作视野往前扩展时可以肉眼捕捉到场景渲染的过程。
我们不必要真的扩充内存,只需要让程序感受到自己拥有了该有的大小即可。
1.5 地址映射
在多道程序系统中,程序所产生的地址是逻辑地址,需要将其转换为内存空间的物理地址。
将逻辑地址转换为物理地址的过程称为地址映射(address mapping)。
逻辑地址使得我们程序猿只需关注指令、数据的逻辑地址,而逻辑地址到物理地址的转换过程我们交由操作系统完成。
二、内存资源管理
下面讨论内存空间的分区方法和分配方法。
2.1 内存分区
2.1.1 静态分区与动态分区
(1)静态分区
静态分区在系统运行之前就将内存空间划分为若干个区域。
当进程需要内存空间时,系统按照某种分配原则为其分配一个或者多个满足要求的区域。通常,分配给进程的内存区域可能比进程实际所需要的区域长。
(2)动态分区
动态分区则是在系统运行的过程中划分内存空间。通常,操作系统可以按照进程所需存储空间大小为其分配恰好满足要求的一个或者多个区域。
2.1.2 等长分区与异长分区
(1)等长分区
等长分区是指将存储空间划分为若干个长度相同的区域。当进程需要存储空间时,系统为其分配一个或多个区域。
(2)异长分区
异长分区是指将存储空间划分为若干个长度不同的区域。当进程需要存储空间时,系统为其分配一个或者多个区域。
实际系统中 ,静态分区和等长分区通常结合在一起,构成静态等长分区的分配形式;动态分区和异长分区通常结合在一起,构成动态异长分区的分配形式。
2.2 内存分配
2.2.1 静态等长分区的分配
这种存储分配形式常用于页式存储管理方式与段页式存储管理方式中。存储空间被静态地划分为若干个长度相等的区域,每个区域长 2 i B 2^{i}B 2iB,称为一个页面(或页)。下面介绍这些页面的分配与去配算法。
1、位图(bitmap)
**位图(bitmap)**用 1 位 (1b) 来代表一个页面的状态,规定当其值为0时,表示该页面为空闲;当其值为1时,表示该页面被占用。设存储空间中共有个页面,所有页面依次编号为0,1,2,…,n - 1,则为了记录所有页面的状态,需要一个表,该表称为位图。
2、空闲页表
**空闲页表(free page table)**中包括两个栏目:首页号和页数。若干个连续的空闲页作为一组登记在空闲页表中。采用此种分配方法能使一个进程的若干个页面尽量连续。
3、空闲页链
将所有的空闲页面连成一个空闲页链(idle page link),分配时可以取链头的页,去配时可以将被释放的页面连入链头。此种方法适用于内存页面的分配,但是对于外存页面的分配因分配和去配均需执行一次数据传输,速度较慢。
2.2.2 *动态异长分区的分配
动态异长分区的分配常用于界地址存储管理方式与段式存储管理方式中。存储空间被动态地划分为若干个长度不等的区域。为了管理这些区域,系统中需要一张表,称为空闲区域表,表中记录着所有当前未被进程占用的空闲区域,当然也可以使用空闲分区链。下面介绍这些区域的分配和去配算法。
1、最先适应算法(first fit,FF)
算法思想:每次都从低地址开始查找,找到第一个能满足大小的空闲分区。
算法实现:
- 空闲分区以地址递增的次序排列。
- 每次分配内存时顺序查找空闲分区表(或空闲分区链接),找到大小能满足要求的第一个空闲分区。
- 如果表目对应区域长度恰好和申请长度相同,那么全部分配。
- 否则将表目的区域分割为两部分,一部分分配,另一部分为原长度和申请长度之差。
优点:尽量使用低地址空间,因而在高地址空间可能形成较大的空闲区域。对于一个较大的空间的请求,可望在较高地址空间得到满足。
缺点:
-
可能分割较大空闲区
如:低地址一个40KB的空闲项,高地址有一个15KB的空闲项,有进程申请10KB的空间,那么显然低地址的空间被优先选择,然后被分割为30KB的空闲项,如果此时又有进程申请35KB的空间,那么系统无法满足要求。
-
由于存储器也属于磨损部件,低地址空间的经常性使用可能使其发生单元损坏的可能性增加,而高区使用较少其损坏的可能性较小
2、下次适应算法(next fit,NF)
某些资料也称之为临近适应算法。为使存储器的低区和高区均匀损,延长存储资源使用寿命,提出了下次适应算法(next fit,NF)。
算法思想:自上次分配空闲区域的下一个位置开始,选取第一个可满足的空闲区域。
算法实现:
- 设置一个循环查找指针,开始时指向表头
- 每次分配从该指针处开始查找(如果找到表尾,则将指针置成表头)第一个遇到的可满足区域。
- 分配后将指针调整为所分配区域的下一个区域。
**优点:**空闲区域分布和分配更加均匀
缺点:可能分割大空闲区域
3、最佳适应算法(best fit,BF)
**最佳适应(best fit,BF)**算法为了克服最先适应算法的缺点而提出。
算法思想:由于动态分区分配是一种连续分配方式,为各进程分配的空间必须是连续的一整片区域。因此为了保证当“大进程”到来时能有连续的大片空间,可以尽可能多地留下大片的空闲区即,优先使用更小的空闲区。
算法实现:空闲分区按容量递增次序链接。每次分配内存时顺序查找空闲分区表(或空闲分区链),找到大小能满足要求的第一个空闲分区。
优点:尽量不分割大的空闲区域
缺点:可能会形成很小以致以后无法利用的空闲区域,即碎片。当系统中的碎片很多的时候,便会造成资源的浪费。
比如当前有3KB, 5KB, 7KB的空闲区域,此时进程发出申请16KB资源的请求,我们就无法满足。
4、最坏适应算法(worst fit,WF)
**最坏适应(worst fit,WF)**算法为了克服最佳适应算法的缺点而提出,,可以在每次分配时优先使用最大的连续空闲区,这样分配后剩余的空闲区就不会太小,更方便使用。
算法实现:空闲分区按容量递减次序链接。每次分配内存时顺序查找空闲分区链(或空闲分区表),找到大小能满足要求的第一个空闲分区。
优点:避免形成碎片。每次如果能拿,只会拿第一个,第一个拿不了也不会往后再找,碎片自然降低。
缺点:分割较大的空闲区域,当遇到较长存储空间的申请命令时,无法满足要求的可能性较大。
算法 | 算法思想 | 分区排列顺序 | 优点 | 缺点 |
---|---|---|---|---|
最先适应算法(FF) | 从头到尾第一个适配的 | 地址递增 | 综合看性能最好。算法开销小,回收分区后一般不需要对空闲分区队列重新排序;有望在高地址满足较大空间请求 | 可能分割较大空闲区,存储部件磨损不均匀 |
下次适应算法(NF) | 从上次适应的位置开始查找 | 地址递增 | 空闲区域分布和分配更加均匀 | 可能分割大空闲区域 |
最佳适应(BF) | 优先使用更小的空闲区 | 容量递增 | 尽量不分割大的空闲区域 | 可能会形成较多难利用的碎片 |
最坏适应算法(WF) | 优先使用最大的连续空闲区 | 容量递减 | 避免形成碎片。 | 较长存储空间的申请命令时,无法满足要求的可能性较大。 |
2.3 碎片与紧凑
动态异长分区存储分配可能形成很小的空闲区域,称为碎片(fagmentation)。如果碎片很多,将会造成严重的存储资源浪费。
解决方法:移动所有的占有区域,以使所有的空闲区域连成一片,这个过程称为紧凑(compaction)。
显然,紧凑的开销是很大的,因为它不仅要修改被移动进程的地址信息,而且要复制进程空间,所以不必要时尽量不做紧凑。
通常仅在请求发生且每个空闲区域单独均不能满足,但所有空闲区域之和能够满足时才进行一次紧凑。
三、界地址存储管理
**单一连续区(single contiguous region)**存储管理又称单对界存储管理方式。一个进程在内存空间的地址由两个参数决定:进程起始地址和长度,称为一个对界。
3.1 基本原理
1.内存空间划分
内存空间采用动态异长分区方法,整个内存被动态地划分为若千个长度各异的区域。
2.进程空间划分
一个进程空间由连续的区域构成。假设进程的长度为 l,则其逻辑地址为0 ~ l - 1。
3.进程空间与内存空间的对应关系
一个进程在内存中占有一个连续的区域。假设进程的长度为 l ,在内存中的起始地址为b,则其物理地址范围为b ~ b + l - 1。
4.所需表目
为实现存储分配和地址映射,需要如下的表目。
-
内存分配表
用于记录内存中所有已经被分配的区域。该表有时可以省略,此时各个分配区域分别登记在占有进程的进程控制块中。
-
空闲区域表
用于记录内存中所有尚未分配的区域。
5.所需寄存器
为了加快地址映射的速度,硬件应当提供以下两个寄存器:
-
首址寄存器
此寄存器整个系统有一个,用于保存正在运行进程的起始地址。
-
限长寄存器
此寄存器整个系统有一个,用于保存正在运行进程的长度。
当一个进程被进程调度程序选中且将要投入运行时,系统将其起始地址和长度由内存分配表或者进程控制块分别取出并送入首址寄存器和限长寄存器。
6.地址映射
地址映射需要将程序产生的逻辑地址转换为内存中的物理地址。
地址映射步骤如下:
- 由程序确定逻辑地址
- 由逻辑地址和限长寄存器的内容相比较以判断是否满足0 ≤ a ≤ l - 1. 如果不满足则为越界,发生越界中断
- 由逻辑地址与首址寄存器的内容相加得到物理地址
3.2 双对界
单对界限制一个进程在内存中只占有一个连续区域,双对界则允许一个进程在内存中占有两个连续的区域。
这两个区域一个可用于保存代码,可为多个进程所共享。
另一个可用于保存数据,为进程所独享。
为实现双对界存储管理,硬件需要提供两对寄存器:代码区首址寄存器和限长寄存器,数据区域首址寄存器和限长寄存器。
取指令时硬件决定使用前一组寄存器,取数据时硬件决定使用后一组寄存器。
双对界经典例子:
UNIX系统将进程空间划分为 I 空间和 D 空间。前者对应指令地址,后者对应数据地址。硬件能够识别逻辑地址所属空间,并使用对应的地址映射寄存器。这是双对界的典型例子。
3.3 交换与重定位
当系统并发度很高时,我们不得不将某些进程暂时调到外存,需要时又要调入内存。
交换技术又称换入换出(swap-in/swap-out)或者(roll-in/roll-out),是指进程内存空间与外存空间之间的动态调度,它是缓解内存空间使用矛盾的一种有效方法。
- 具有对换功能的操作系统中,通常把磁盘空间分为文件区和对换区两部分。文件区主要用于存放文件,主要追求存储空间的利用率,因此对文件区空间的管理采用离散分配方式;对换区空间只占磁盘空间的小部分,被换出的进程数据就存放在对换区。由于对换的速度直接影响到系统的整体速度,因此对换区空间的管理主要追求换入换出速度,因此通常对换区采用连续分配方式(文件管理章节会介绍)。总之,对换区的I / O速度比文件区的更快。
- 交换通常在许多进程运行且内存吃紧时进行,而系统负荷降低就暂停。例如:在发现许多进程运行时经常发生缺页,就说明内存紧张,此时可以换出一些进程;如果缺页率明显下降,就可以暂停换出。
- 可优先换出阻塞进程;可换出优先级低的进程;为了防止优先级低的进程在被调入内存后很快又被换出,有的系统还会考虑进程在内存的驻留时…
- 被换出的进程再次运行之前必须重新换入内存,而再次进入内存时的存放位置与换出之前在内存中的存放位置一般有所不同,这就要求程序编址与内存存放位置无关,这种程序称为可重定位程序。由0起始编址的程序都满足重定位要求,这样的程序也称为浮动程序。
3.4 覆盖技术
早期的计算机内存很小,比如IBM 推出的第一台PC机最大只支持 1MB 大小的内存。因此经常会出现内存大小不够的情况。
覆盖技术就是用来解决较大进程装入较小进程空间的一种技术。
基本思想:只将全局代码和数据静态的放在内存中,其他部分则分阶段地动态装入,后装入的对象重复使用以前对象所占用的空间,即覆盖以前的对象,这些动态装入的成分也称为覆盖。
程序员需要将程序划分为若干个程序段,并根据访问和调用关系规定它们的执行和覆盖次序,而且需要编写一个覆盖驱动程序(overlay driver)。
例:一个包括4遍扫描的编译程序,运行时既可以对应4个进程,也可以通过覆盖由个进程完成。一个进程完成4遍扫描,将符号表等公共数据作为共享成分为其静态分配空间,扫描程序则动态装入,每次扫描结束时转覆盖驱动程序装入下一次扫描代码,如下图所示。
四、页式存储管理
界地址存储管理方式要求一个进程占有内存空间中的一个连续区域,因而采用动态异长存储分配方法可能产生碎片。相反,页式(paging,也称分页)存储管理方式允许一个进程占有内存空间中的多个连续区域,而且这些区域的长度相同,因而采用静态等长存储分配方法,不会产生碎片。
4.1 基本原理
1、内存空间划分
内存空间被静态的地划分为若干个等长的区域,每个区域称为一个物理页框(page frame)。每个页框通常有 $ 2^{i} $个单元(i 为正整数)。将其由0开始依次编址,称为页内地址。
设内存的容量为 2 n 2^{n} 2n B,则共有 2 n − i 2^{n-i} 2n−i 个页框。将所有页框由 0 开始依次编号,称为页框号。易见,第 k 个页框的起始地址(即首址)为k x 2 i 2^{i} 2i
一个内存单元的地址称为物理地址。显然,物理地址可以通过下式计算得到:
物理地址
=
物理页框首址
+
页内地址
=
页框号
×
2
i
+
页内地址
物理地址 = 物理页框首址 + 页内地址 = 页框号 \times 2^{i} + 页内地址
物理地址=物理页框首址+页内地址=页框号×2i+页内地址
2、进程空间划分
进程空间也被静态地划分为若干个等长的区域,每个区域称为一个逻辑页面,其长度与页框的长度相同,即共有 2 i 2^{i} 2i个单元(i 为正整数)。
将其由0开始依次编址,称为页内地址。
设进程共有 l 个逻辑页面,将其由0开始依次编号,称为逻辑页号。易见,第 k 个逻辑页面的起始地址(即首址)为
k
×
2
i
k\times2^{i}
k×2i.
一个进程单元的地址称为逻辑地址。显然,逻辑地址可以通过下式计算得到:
逻辑地址
=
逻辑页首址
+
页内地址
=
逻辑页号
×
2
i
+
页内地址
逻辑地址 = 逻辑页首址 + 页内地址 = 逻辑页号 \times 2^{i} + 页内地址
逻辑地址=逻辑页首址+页内地址=逻辑页号×2i+页内地址
实际上,将逻辑页号作为高位,页内地址作为低位,即可得到逻辑地址.
3、进程空间和内存空间的对应关系
操作系统以页框为单位为各个进程分配内存空间。
进程的每个逻辑页面分别放入一个物理页框中,也就是说进程的页面和内存的页框有一一对应的关系。
各个页面不必连续存放,可以放到不相邻的各个页框中。
4、所需表目
为了实现逻辑地址与物理地址之间的转换,系统中需要以下两个表目。
页表。该表用于记录进程的逻辑页面与内存页框之间的对应关系。由于逻辑页号是连续的,因而可将其省略。对于一个给定的逻辑页号,将其与页表的起始地址相加后便可得到对应的页框号在页表中的入口地址。
- 一个进程对应一张页表
- 进程的每个页面对应一个页表项
- 每个页表项由“页号”和“块号”组成
- 页表记录进程页面和实际存放的内存块之间的映射关系
总页表。该表用于记录页框的使用情况,其形式、页框的分配与去配算法在前面的静态等长分区分配中已经有过介绍。
5、所需寄存器
-
页表首址寄存器:用于保存正在运行进程的页表的首址。在一个进程被低级调度程序选中并投入运行之前,系统将其页表首址由进程控制块中取出并送入该寄存器。
-
页表长度寄存器:用于保存正在运行进程页表的长度。在一个进程被低级调度程序选中并投入运行之前,系统将其页表长度由进程控制块中取出并送入该寄存器。
-
一组联想寄存器(associative registers)——快表(translation lookaside buffer,TLB,又称变换旁查缓冲器):用于保存正在运行进程的页表中的部分项目。
当访问一个页面时,首先根据逻辑页号在快表中进行查找,如果找到则根据页框号及页内地址形成物理地址:如果找不到则由逻辑页号在页表中进行查找,并将找到的页框号与逻辑页号合在一起放入快表中。如果快表已满,则按照某种置换算法淘汰一个。由于逻辑页号在快表中不再是连续的,因而不能省略它。
页表和TLB在计组中已经学的很详细了,就不再赘述。
6、地址映射
逻辑地址向物理地址的转换。
逻辑页号p,页内地址d => 页框号f,页内地址d(页内地址不变)
地址映射步骤:
- 指令产生逻辑地址(p,d)
- 逻辑页号 p 查快表得到页框号f
- 没找到
- 由逻辑页号 p 与页表长度寄存器中的内容l相比较以判断是否满足0 ≤ p ≤ l - 1。如果不满足则为越界,发生越界中断。
- 由逻辑页号 p 与页表首址寄存器中的内容 b 查页表得到页框号 f
- 由页框号 f 与页内地址 d 合并得到物理地址(f d)。
将(p, f)送入快表中。如果此时快表已满,则按置换算法淘汰一个
- 找到
- 由页框号 f 与页内地址 d 合并得到物理地址(f d)。
- 没找到
实现时,我们往往在页表中增加一个有效位(valid bit),当该位为1表示有效,否则无效。
页表访问时间
=
快表命中率
×
(
快表访问时间
+
内存访问时间
)
+
快表不命中率
×
(
快表访问时间
+
2
×
内存访问时间
)
页表访问时间 = 快表命中率 \times (快表访问时间 + 内存访问时间) + 快表不命中率 \times (快表访问时间 + 2\times内存访问时间)
页表访问时间=快表命中率×(快表访问时间+内存访问时间)+快表不命中率×(快表访问时间+2×内存访问时间)
页表访问也属于内存访问, 所以TLB不命中时是两次内存访问
4.2 多级页表
单级页表存在的问题
当内存空间和进程空间增长,页表的长度也会随之增长。
假如我们有逻辑寻址空间位32位的操作系统,页面长度为12位,那么一个进程最多可以拥有 2 20 2^{20} 220个页面。
那么我们页表就要有 2 20 2^{20} 220项,页表的大小就是 2 20 × 页表项长度 2^{20} \times 页表项长度 220×页表项长度,我们操作系统提供这么大一块连续空间是很困难的。
而且没有必要让整个页表常驻内存,因为进程在一段时间内可能只需要访问某几个特定的页面。
因此,我们通常选择多级页表,即将页表多级存放。
我们以上面 2 20 2^{20} 220的页表的两级页表为例:
2 20 = 2 10 × 2 10 2^{20} = 2^{10} \times 2^{10} 220=210×210
那么我们可以开 2 10 2^{10} 210个 2 10 2^{10} 210的页表, 即:
那么查询有何变化呢?
- 按照地址结构将逻辑地址拆分成三部分
- 从PCB中读出页目录表始址,再根据一级页号查页目录表,找到下一级页表在内存中的存放位置
- 根据二级页号查表,找到最终想访问的内存块号
- 结合页内偏移量得到物理地址
4.3 反置页表
反置页表(inverted page table), 听名字就倒反天罡 面向内存物理页框. 即, 对应内存的每一个物理架构设置一个表项, 表项的序号就是物理页框号. 表项内容则是进程pid 和 逻辑页号p. 下面是反置页表的示例图:
如果就这样朴素实现的话, 我们在反置页表中查找匹配表项最坏时间复杂度是O(L), L为反置页表长度
考虑优化, 对于查找的优化方式较为常用的是哈希(也称散列, 杂凑)技术, 这要求我们设计哈希函数 hash(pid, p), 用于得到查询的入口地址, 从该处开始查询. 当然, 哈希技术免不了哈希冲突.
对于访问, 我们也可以设置TLB保存最近访问过的入口项来加快访问速度.
五、段式存储管理
5.1 基本原理
1、内存空间划分
内存空间被动态地划分为若干个长度各异的区域,每个区域称为一个物理段。每个物理段在内存中有一个起始地址,称为段首址。将物理段中的所有单元由 0 开始依次编址,称为段内地址。
对于一个长度为m的段来说,其段内地址依次为0,1,…,m - 1。内存中一个单元的位置被称为物理地址。
写过汇编其实还是比较好理解,因为汇编往往先要书写段约定部分。
2、进程空间划分
进程空间被静态地划分为若干个长度各异的区域,每个区域称为一个逻辑段。
一个逻辑段通常对应一个程序单位,例如一个主程序、一个子程序、一个数据区、一个模块等。
将一个逻辑段中的所有单元由0开始依次编址,称为段内地址。对于一个长度为 n 的段来说,其段内地址依次为0,1,…,n - 1。每个逻辑段具有一个符号名字,称为段名。将一个进程的所有逻辑段由 0 开始依次编号,称为段号。
对于一个由 n 个逻辑段所构成的进程来说,其段号依次为0,1,…,n - 1。
3、进程空间和内存空间对应关系
进程的一个逻辑段对应内存的一个物理段。一个进程的若干个逻辑段可以存放于内存若干个不相连的物理段中。
物理上,进程的段内地址连续,而段间未必连续。
4、所需表目
为了实现地址映射,系统需要保存若干个表目,包括段表、空闲表等。
- 段表:每个进程都有一张段表,表项内存放段基址和段长。表项偏移对应段号。
- 空闲表:记录并管理内存中的空闲区域。
5、所需寄存器
与页式存储管理相类似,为了加快地址映射的速度,硬件通常提供以下3组寄存器。
- 段表首址寄存器:用于保存正在运行进程的段表的首址。在一个进程被低级调度程序选中并投入运行之前,系统将其段表首址由进程控制块中取出并送入该寄存器。
- 段表长度寄存器:用于保存正在运行进程的段表的长度。在一个进程被低级调度程序选中并投入运行之前,系统将其段表长度由进程控制块中取出并送入该寄存器。
- 一组联想寄存器(快表):用于保存正在运行进程的段表中的部分项目,即当前正在访问的段所对应的项目。其作用、用法与页式存储管理相仿。由于段号在快表中不再是连续的,因而不能省略它。
6、地址映射
逻辑地址:逻辑段号s,段内偏移d => 物理地址:物理段号b’,段内偏移d
地址映射步骤:
-
由程序确定逻辑地址(s,d)
-
由 s 查询TLB得到段首址 b’ 和 段长 l’
-
如果未查到
- 将s和段表长度寄存器的 l 比较判断是否越界(0 <= s <= l - 1)
- 越界则发生越界中断
- 由段号 s 和 段表首址寄存器内容 b 查找内存段表得到段首址b’和段长l’
- 由b’ 和 段内偏移d得到物理地址b’ + d
- 将(s, b’, l’)送入TLB,如果TLB已满,则按照某种替换算法淘汰一个。
- 将s和段表长度寄存器的 l 比较判断是否越界(0 <= s <= l - 1)
-
5.2 段的保护与共享
1、段的共享
一个进程的段号是连续的,而段与段对应的物理段之间却不一定连续。如果某一进程的一个段号 s i s_{i} si与另一进程的一个段号 s j s_{j} sj对应同一段首址和段长,即可实现段的共享。
2、段的保护
进程对于共享段的访问往往需要加上某种限制。
例如,对于保存共享代码的段,任何进程都不能修改它;对于具有保密要求的段,某些进程不能读取它;对于属于系统数据的段,某些
进程不能修改等。
为此需要增加对共享段的“访问权限”一栏。我们可以在段表项中加入三个标记位R、W、X(类似于Linux的rwx),即读、写、执行权限。
为了实现段的共享和保护,系统中还需要一个共享段表,该表中记录着所有共享段。
当多个进程共享同一段时,这些进程的段表中的相应表目指向共享段表中的同一表目,
共享段表以“段名”来识别和查找共享段;“共享计数”记录当前有多少个进程正在使用该段,当其值为0时为空闲表项,当一个共享段初次被使用时,它被登记在共享段表中,共享计数置为1。以后其他进程访问此时,其共享计数值加1;当一个进程结束对于某一共享段的访问时,其共享计数值减1。当减到0时,表示没有进程在使用该段,可以释放所占用的存储空间。
六、段页式存储管理
页式存储管理 VS 段式存储管理
页是信息的物理单位。分页的主要目的是为了实现离散分配,解决碎片问题,提高内存利用率。分页仅仅是系统管理上的需要,完全是系统行为,对用户是不可见的。
段是信息的逻辑单位。分段的主要目的是更好地满足用户需求。一个段通常包含着一组属于一个逻辑模块的信息。分段对用户是可见的,用户编程时需要显式地给出段名。
优点 | 缺点 | |
---|---|---|
分页管理 | 内存空间利用率高,不会产生外部碎片,只会有少量的页内碎片 | 不方便按照逻辑模块实现信息的共享和保护 |
分段管理 | 很方便按照逻辑模块实现信息的共享和保护 | 如果段长过大,为其分配很大的连续空间会很不方便。另外,段式管理会产生外部碎片 |
世界是一个巨大的套娃——段页式管理
结合二者优点,摒弃二者缺点,就有了我们的段页式存储管理。
6.1 基本原理
1、内存空间划分
与页式存储管理相同,内存空间被静态地划分为若干个长度相同的区域,每个区域长 2 i 2^{i} 2i个单元,称为一个页框。
2、进程空间划分
与段式存储管理相同,进程空间被静态地划分为若干个长度不同的区域,称为一个逻辑段。与页式存储管理相同,每段空间被静态地划分为若干个长度相同的区域,每个区域长 2 i 2^{i} 2i个单元,称为一个逻辑页面。
由于段长不定,所以每段的最后一页可能会有碎片。
3、进程空间和内存空间的对应关系
进程空间的一个逻辑页面对应内存空间的一个页框。同一段内的逻辑页面是连续的,而对应的页框却未必连续。
4、所需表目
为了实现地址映射,系统中需要保存三类表目,即段表、页表和总页表。
- 段表:此表每个进程有一个,用于记录各段的页表长度与页表首址
- 页表:此表每个段有一个,用于记录一段中各个逻辑页号与页框号之间的对应关系
- 总页表:即位图,用于记录并管理内存页面。
5、所需寄存器
- 段表首址寄存器:与段式存储管理完全相同。
- 段表长度寄存器。与段式存储管理完全相同。
- 一组联想寄存器(快表)。用于保存正在运行进程的段表和页表中的部分表目。本应有快段表和快页表这两张快表,但是在实现时通常将其合并在一起。
6、地址映射
地址映射需要将逻辑地址转换成物理地址,即完成如下映射:
逻辑地址:段号s、逻辑页号p、页内偏移d => 物理地址:物理页框 f,页内偏移d
地址映射步骤:
- 指令产生逻辑地址(s, p, d)
- 段号s和逻辑页号p查找快表得到物理页框号f
- 若没找到
- 段号s 和 段表长度寄存器中的内容 l 比较来判断是否满足 0 <= s <= l - 1,不满足则发生越界中断
- 根据段号s 和 段首址寄存器中的 b 来查找段表项得到页表首址b’和页表长度l’
- 逻辑页号与页表长度相比较以判断是否满足 0 <= p <= l’ - 1。如果不满足则发生越界中断
- 将逻辑页号 p 与页表首址b’ 查找页表来得到页框号f
- (s, p, f)送入TLB,如果快表已满,则按照某种置换算法淘汰一个。
- 若没找到
- f 和 d合并得到物理地址
段表首址寄存器:与段式存储管理完全相同。
2. 段表长度寄存器。与段式存储管理完全相同。
3. 一组联想寄存器(快表)。用于保存正在运行进程的段表和页表中的部分表目。本应有快段表和快页表这两张快表,但是在实现时通常将其合并在一起。[外链图片转存中…(img-Xym3EeSu-1717924658694)]
6、地址映射
地址映射需要将逻辑地址转换成物理地址,即完成如下映射:
逻辑地址:段号s、逻辑页号p、页内偏移d => 物理地址:物理页框 f,页内偏移d
地址映射步骤:
- 指令产生逻辑地址(s, p, d)
- 段号s和逻辑页号p查找快表得到物理页框号f
- 若没找到
- 段号s 和 段表长度寄存器中的内容 l 比较来判断是否满足 0 <= s <= l - 1,不满足则发生越界中断
- 根据段号s 和 段首址寄存器中的 b 来查找段表项得到页表首址b’和页表长度l’
- 逻辑页号与页表长度相比较以判断是否满足 0 <= p <= l’ - 1。如果不满足则发生越界中断
- 将逻辑页号 p 与页表首址b’ 查找页表来得到页框号f
- (s, p, f)送入TLB,如果快表已满,则按照某种置换算法淘汰一个。
- 若没找到
- f 和 d合并得到物理地址