连续分配:为用户进程分配的必须是一个连续的内存空间。
非连续分配:为用户进程分配的可以是一些分散的内存空间。
将内存空间分为一个个大小相等的分区(比如:每个分区4KB),每个分区就是一个“页框”)。
注意:页框 = 页帧 = 内存块 = 物理块 = 物理页面。
每个页框有一个编号,即“页框号”。页框号从0开始。
注意:页框号 = 页帧号 = 内存块号 = 物理块号 = 物理页号。
将进程的逻辑地址空间也分为与页框大小相等的一个个部分,每个部分称为一个“页”或“页面”。每个页面也有一个编号,即“页号”,页号也是从0开始。
如上图进程A的逻辑地址空间为,即进程A的空间大小为16KB,因此,进程A可以被分成4个页。
进程的各个页,会被放到内存的各个页框当中。
操作系统以页框为单位为各个进程分配内存空间。进程的每个页面分别放入一个页框中。也就是说,进程的页面与内存的页框有一一对应的关系。
各个页面不必连续存放,可以放到不相邻的各个页框中。
注意,易混淆点:
页、页面 vs 页框、页帧、物理页;
页号、页面号 vs 页框号、页帧号、物理页号。
左侧——指的是进程在逻辑上被划分为一个个的部分。
右侧——指的是内存在物理上被划分为一个个的部分。
为了能知道进程的每个页面在内存中的存放位置,操作系统要为每个进程建立一张页表。
注:页表通常存放在PCB(进程控制块)中。
说明
1.一个进程对应一张页表;
2.进程的每个页面对应一个页表项;
3.每个页表项由“页号”和“块号”组成;
4.页表记录进程页面和实际存放的内存块之间的映射关系。
问题1:“页表”是存放在PCB中,从而也是存放在内存中的。那么,页表中的每个页表项占多大空间?占几个字节?
举一道题为例作为说明。
例题:假设某系统物理内存大小为4GB,页面大小为4KB,则每个页表项至少应该为多少字节?
1)分析
先分析4GB大小的物理内存,到底能够在物理上分为多少个页框。
我们知道,物理内存的页框/内存块的大小,与进程的页面大小是相等的。
内存块大小 = 页面大小 = 4KB = 。
因此,4GB的内存总共会被分为4GB / 4KB = 个内存块。
既然物理内存中总共有这么多个内存块,因此,要给这些内存块编号,则编号的范围自然就是0 ~ 。
而如果要用二进制0、1编码来表示这么多个内存块的编号,则至少需要20bit来表示。
即,在页表的页表项当中,对于“块号”这个参数,它至少需要20bit来存放。
但是,计算机的存储是以字节为单位的,而并不是以bit为单位的,所以要转换为多少个字节。
至少要用3B来表示块号(3×8 = 24bit)。
重要考点:
计算机中内存块的数量 —> 页表项中块号至少占多少字节。
那么“页号”又要占多少个字节呢?
实际上,由于页表项连续存放,因此页号可以是隐含的,不占存储空间(类比数组)。
假设页表中的各页表项从内存地址为X的地方开始连续存放,如何找到页号为的页表项?
号页表项的存放地址 = 。
学过数据结构的线性表,此处不难理解。
2)答
注意:页表记录的只是内存块号(如:编号为8的内存块号/页框号),而不是内存块的起始地址。而对于内存块实际的物理起始地址,还需经过一个公式进行转换:
问题2:如何通过页表实现逻辑地址到物理地址的转换?
补充:如果进程在内存中是连续存放的,如何进行逻辑地址到物理地址的转换。
接下来讨论分页存储如何实现逻辑地址到物理地址的转换。
特点:虽然进程的各个页面是离散存放的,但是页面内部是连续存放的。
基于这个特点,如果要访问逻辑地址A,则:
a.确定逻辑地址A对应的“页号”P;
b.找到P号页面在内存中的起始地址(需要查页表);
c.确定逻辑地址A的“页内偏移量”W;
上述信息若均已得到,则由下述公式即可算出逻辑地址A对应的物理地址。
子问题:如何确定一个逻辑地址对应的页号、页内偏移量?
还是以一道例题进行说明。
例题:在某计算机系统中,页面大小是50B。某进程逻辑地址空间大小为200B,则逻辑地址110对应的页号、页内偏移量是多少?
1)分析
由于计算机按字节存储,因此每1B为一个存储单元。因此,如上图所示,逻辑地址110对应的页号是,并且相对于2号页面的起始地址而言,页内偏移量应该是。
2)如何计算
页号 = 逻辑地址 / 页面长度(取除法的整数部分)
页内偏移量 = 逻辑地址 % 页面长度 (取除法的余数部分)
页号 = 110 / 50 = 2;
页内偏移量 = 110 % 50 = 10。
逻辑地址 可以拆分为 (页号,页内偏移量)。
通过页号查询页表,可知页面在内存中的起始地址。
页面在内存中的起始地址 + 页内偏移量 = 实际的物理地址。
子问题:为何页面大小要取2的整数幂?
在计算机内部,地址是用二进制表示的,如果页面大小刚好是2的整数幂,则计算机硬件可以很快速地把逻辑地址拆分成。
结论:如果每个页面大小为,用二进制数表示逻辑地址,则末尾 K 位即为页内偏移量,其余部分就是页号。
(熟悉二进制乘法、二进制除法,无符号左移、无符号右移等操作的话,对此处的原理就能够很轻易的理解了)
总结:页面大小刚好是2的整数幂有什么好处?
1.逻辑地址的拆分更加迅速——如果每个页面大小为,用二进制数表示逻辑地址,则末尾K位即为页内偏移量,其余部分就是页号。因此,如果让每个页面的大小为2的整数幂,计算机硬件就可以很方便地得出一个逻辑地址对应的页号和页内偏移量,而无需进行除法运算,从而提升了运行速度。
2.物理地址的计算更加迅速——根据逻辑地址得到页号,根据页号查询页表从而找到页面存放的内存块号,将二进制表示的内存块号和页内偏移量拼接起来,就可以得到最终的物理地址。
提示:学有余力的可以看看二进制数的运算(计组内容),能更好的理解本质原理。
分页存储管理的逻辑地址结构如下所示:(以地址长度32位为例)
地址结构包含两个部分:
前一部分为页号P,后一部分为页内偏移量W。
在上图所示的例子中,地址长度为32位,其中位为“页内偏移量”,或称“页内地址”;位为“页号”。
如果有K位表示“页内偏移量”,则说明该系统中一个页面的大小是个内存单元;
如果有M位表示“页号”,则说明在该系统中,一个进程最多允许有个页面。
重要:页面大小 <------> 页内偏移量位数 ------> 逻辑地址结构。
提示:
有个别题目中,页面大小有可能不是2的整数次幂,这种情况还是得用最原始的方法计算:
页号 = 逻辑地址 / 页面长度(取除法的整数部分)
页内偏移量 = 逻辑地址 % 页面长度 (取除法的余数部分)