文章目录
无论是分页、分段还是虚拟映射,他们都是属于操作系统内存管理的一种手段。其核心目的是为了更好的利用宝贵的内存资源
1.分页
1.1 什么是分页
将一个进程的地址空间划分成若干个大小相等的区域,称为页。相应地,将主存空间划分成与页相同大小的若干个物理块,称为块或页框。在为进程分配主存时,将进程中若干页分别装入多个不相邻接的块中。

1.2 为什么分页
于内存来说,连续的地址空间资源是十分宝贵的。对于一个大作业,想要装入内存当中是一件不容易的事情。如果我们将大作业打散成等大小的区块,那么再装入内存当中就会是一件容易的事情
作业打散前

作业打散后

1.3 页表
当进程离散的存储在主存中的各个部位,计算机在运行进程时,需要能够找到页在主存中存储的位置。这个时候就需要引入页表,通过页表记录页和主存物理块的对应关系

值得一提的是,页表实际存储过程中,页号是隐含的。因为每行元素的大小都是固定的,因此可以像数组下标那样进行索引
1.4 地址结构
假设页大小为4KB,一进程A大小64KB,现有一逻辑地址为4097,对其应的页号、页内偏移量为多少
进程A大小64KB,页大小为4KB,因此A可以划分为16个页。
我们将4KB转换为B,即4096个字节。那么逻辑地址的页号、页内偏移量的计算方式如下
页号 = 逻辑地址 / 页大小 = 4097 / 4096 = 1 页号 ~ = ~ 逻辑地址 / 页大小 ~ = ~ 4097 ~ / ~ 4096 = 1\\ 页号 = 逻辑地址/页大小 = 4097 / 4096=1
页内偏移量
=
逻辑地址
%
页大小
=
4097
%
4096
=
1
页内偏移量 ~ = ~ 逻辑地址~ \%~ 页大小 = 4097 ~ \% ~ 4096 = 1
页内偏移量 = 逻辑地址 % 页大小=4097 % 4096=1

上面,我们从十进制的角度出发,解读公式的计算方式。接下来,我们通过二进制的视角分析该问题
假设是32位的操作系统, 4096 = 2 12 4096 = 2^{12} 4096=212,我们将低12位用黑色数字表示、高20位用红色表示
4096可以表现为
00000000000000000001000000000000
那么逻辑地址4097可以表现为如下形式
00000000000000000001000000000001
我们发现,红色部分的数值恰好就等于1,也就是页号;黑色部分的数值恰好也等于1,也就是页内偏移量
我们再距一个例子7362,
00000000000000000001110011000010
红色部分恰好为1,也就是页号;黑色部分为3,266,也就是页内偏移量。
我们在用除法、取模公式计算
页号
=
7362
/
4096
=
1
页号=7362/4096=1
页号=7362/4096=1
页内偏移量
=
7362
%
4096
=
3266
页内偏移量=7362\%4096=3266
页内偏移量=7362%4096=3266
因此,对于页大小为 2 n 2^n 2n次方时,页内偏移量为低n位;页号为高32-n位(32位操作系统)
进一步,我们可以推导出如下公式
int pageSize = 4096;
int n = Integer.bitCount(pageSize - 1);
int pageNumber = address & (1 << n); // 逻辑地址取低n位
int pageOffset = address >> n; // 逻辑地址取高位,舍弃低n位
tip:上述取整、求余的前提是pageSize是 2 n 2^n 2n
因此,我们可以总结出分页情况下,逻辑地址的规律。在pageSize = 4KB,32位操作系统时,逻辑地址结构如下

tip: 页内偏移量有时也叫页内地址
1.5 地址转换
为了方便解释,本节将不再通过二进制的形式表示地址信息。而是通过十进制的方式表示。如下图所示,我需要定位**逻辑地址(4, 256)**对应的物理地址,其中(4, 256)的意思是:逻辑地址所在页号为4, 页内偏移量为256。

具体转换过程如下
- 判断页号是否合法(是否越界,如果是,则中断)
- 拼接页表起始地址,找到页表中对应的页号
- 同故宫页表,找到物理块号
- 拼接物理块号,页内偏移地址,找到物理地址(15, 256)
1.6 块表
在整个地址映射过程中,页式存储过程中至少发生2次主存访问。第一次:找到页表,确定物理地址;第二次,从物理地址中获取数据
我们可以通过增加一组小容量的联想寄存器,存储高频访问的页表数据,以此提高内存访问效率
1.7 两级页表
当一个进程很大的时候,对应的页表大小也会非常庞大。光光是维护页表就需要操作系统开辟一块很大的连续空间
因此,我们可以对页表分页存储,通过两级页的方式解决页表过大的问题
首先对进程分页,引入页表管理页和物理块之间的对应关系;然后我们对页表分页,引入新的页表管理之前的页表的物理地址
2. 分段
整体思路和分页类似,都是将大的作业拆分为小作业。通过引入全新的数据结构来维护小作业和物理地址之间的映射关系
不过分段的划分思路是,将程序完整的逻辑信息划分为一段。比如main函数所在程序划分一段、全局变量划分一段。段的划分方式保证逻辑信息一致的代码内容划分到同一段内,而这导致每一段的大小不一定是相等的

2.1 段表
和页表类似,维护段在主存当中的物理地址和段的映射关系。记录段在主存中的起始地址(或者叫做基址)和段的长度
2.2 逻辑地址
在逻辑地址中,允许一个作业有64Kb个段、每个段最大长度为64Kb

2.3 地址转换
和页式管理的转换方式类似

3. 虚拟存储
在最开始的存储管理中,必须为每个作业分配足够的空间,以便装入全部信息。当主存空间不能满足作业要求时,作业无法装入主存执行。
如果一个作业只部分装入主存便可开始启动运行,其余部分暂时留在磁盘上,在需要时再装入主存,这样可以有效地利用主存空间。从用户角度看,该系统所具有的主存容量将比实际主存容量大得多,人们把这样的存储器称为虚拟存储器。虚拟存储器是为了扩大主存容量而采用的一种设计方法,其容量是由计算机的地址结构决定的。
3.1 虚拟存储器的实现
虚拟存储器是具有请求调入功能和置换功能,能仅把作业的一部分装入主存便可运行作业的存储器系统,是能从逻辑上对主存容量进行扩充的一种虚拟的存储器系统。
其逻辑容量由主存和外存容量之和以及 CPU 可寻址的范用来决定,其运行速度接近于主存速度,成本也下降。虚拟存储器的实现主要有如下3种方式
- 请求分页系统
- 请求分段系统
- 请求段页式系统
不论是哪种方式,都只会加载作业的一部分。当运行时需要使用的页/段不在主存中时,就会发生缺页/缺段中断,然后进行请求调页,页面置换,将原本不在主存中的数据加载如主存中
3.2 请求分页管理实现
请求分页是在纯分页系统的基础上增加了请求调页功能、页面置换功能所形成的页式虚拟存储系统。
请求分页的页表机制是在纯分页的页表机制上形成的,由于只将应用程序的一部分调入主存,还有一部分仍在磁盘上,故需在页表中再增加若干项(如状态位、访问字段和辅存地址等)供程序(数据)在换进、换出时参考。
在请求分页系统中,每当所要访问的页面不在主存时便要产生一个缺页中断,请求OS将所缺的页调入主存,这是由缺页中断机构完成的。缺页中断与一般中断的主要区别如下。
- 缺页中断在指令执行期间产生和处理中断信号,而一般中断在一条指令执行完,下一条指令开始执行前检查和处理中断信号。
- 发生缺页中断时,返回到被中断指令的开始重新执行该指令,而一般中断返回到下一条指令执行。
- 一条指令在执行期间可能会产生多次缺页中断。
3.3 页面淘汰算法
因为页表大小是有限的,当发生请求缺页时,页表已满的情况下,我们需要淘汰一些已经有的页表项,从而将新的页表项加入。选择何种淘汰算法,以达到最低的缺页率是提高系统性能的一个非常重要的手段。常见的页面淘汰置换算法如下
1. 最佳(Optimal)置换算法
每次淘汰都淘汰那些未来一段时间内,最长时间都不会用到的页。这是一种理想的算法,很难实现。因为现在的视角是无法判断未来哪些页会被使用到
假定系统为进程P1分配了3个物理块,该进程访问页面的顺序为“0,7,6,5,7,4,7,3,5,4,7,4,5,6,5,7,6,0,7,6”,利用最佳置换算法,求缺页中断次数、页面置换次数和缺页率。

根据题意系统为P1分配了3个物理块,故P1开始运行申请的0、7、6三个页面将产生缺页中断,但不需要置换页面(因为刚开始分配的内存物理块“空闲”);当进程访问页面5时产生缺页中断,由于页面0将在第18次才被访问,根据最佳置换算法0、7、6三页中0页将最久不被访问的页面,所以被淘汰;接着访问页面7,发现已在主存中,不会产生缺页中断,依此类推。
从上分析可知,采用最佳置换算法产生了9次缺页中断,发生了6次页面置换(前3次无需页面置换),缺页率f=缺页次数/访问次数=9/20=45%。
2. FIFO先进先出
这种算法异常简单粗暴,有限淘汰最先进入的页表项
3. LRU最近最久未使用算法
这种算法需要维护每个页上一次使用到现在的时间,记为t。每次淘汰页面的时候,淘汰t最大的
本文详细阐述了分页、分段和虚拟存储在操作系统内存管理中的作用,包括页表、地址结构、页面淘汰算法(如最佳置换、FIFO和LRU)等内容,旨在揭示这些技术如何优化内存资源利用。


383

被折叠的 条评论
为什么被折叠?



