操作系统3.1.6 基本分页存储管理

回顾:连续分配方式的缺点

支持多道程序的两种连续分配方式:

1、固定分区分配:缺乏灵活性,会产生大量的内部碎片,内存利用率低

2、动态分区分配:会产生很多外部碎片,虽然可以用紧凑技术处理,但是代价很高

因此人们思考能否将一个进程分散地装入许多不相邻的分区中,便可以充分地利用内存,而无需再进行紧凑技术了。

基于此,引入非连续分配方式(离散分配方式)。

 

一、把“固定分区分配”改造为“非连续分配版本”

假设进程A大小为23MB,但是每个分区大小只有10MB,如果进程只能占用一个分区,显然放不下。

解决思路:将进程拆分为10+10+3三个部分,再将三个部分分别放到三个分区中(这些分区不要求连续

此时进程A的最后一个部分是3MB,放入分区后会产生7MB的内部碎片。

如果每个分区大小为2MB,那么进程A可以拆分成11*2MB+1MB共12个部分,只有最后一部分1MB占不满分区,会产生1MB的内部碎片。

显然,如果把分区大小再设置的更小一些,内部碎片会更小,内存利用率会更高

基本分页存储管理的思想——把内存分为一个个相等的小分区,再按照分区大小把进程拆分成一个个小部分。

 

二、分页存储管理的基本概念

将内存空间分为一个个大小相等的分区(比如:每个分区4KB),每个分区就是一个“页框”。或称“页帧”、“内存块”、“物理块”。

每个页框有一个编号,即“页框号”(或者“内存块号”、“页帧号”、“物理块号”)页框号从0开始

 

将用户进程的地址空间也分为与页框大小相等的一个个区域,称为“”或“页面”。

每个页面也有一个编号,即“页号”,页号也是从0开始

(注:进程的最后一个页面可能没有一个页框那么大。因此,页框不能太大,否则可能产生过大的内部碎片)

操作系统以页框为单位为各个进程分配内存空间。进程的每个页面分别放入一个页框中。也就是说,进程的页面与内存的页框一一对应的关系。

各个页面不必连续存放,也不必按先后顺序,可以放在不相邻的各个页框中。

 

三、如何实现地址的转换

进程分页后,进程的各个页面可以放在不连续的页框中,所以如何实现逻辑地址到物理的地址的转换?

如下图,将下面的进程分页,假设每页大小为50B,那么就分为4个页面。

指令1需要访问逻辑地址为80的单元,逻辑地址为80的内存单元在1号页,如果1号页在内存中的起始位置为450,逻辑地址为80的内存单元相对于该页的起始地址而言,偏移量为30,所以实际物理地址 = 450 + 30 = 480

所以要将逻辑地址转化为实际地址需要:

  1. 算出逻辑地址对应的页号
  2. 知道该页号对应的页面在内存中的起始地址
  3. 计算出逻辑地址在页面内的偏移量
  4. 物理地址 = 页面起始地址 + 偏移量

手动计算方法:

页号 = 逻辑地址 / 页面长度(取整数部分)(如刚刚那个例子,页号 = 80/50 = 1)
页内偏移量 = 逻辑地址 % 页面长度(取除法的余数部分)(页内偏移量 = 80%50 = 30)
页面在内存中的起始位置:操作系统需要用某种数据结构记录进程各个页面的起始位置(1号页在内存中存放的起始位置450)

 

对于计算机,通常将页面的大小划分为2的整数次幂

假设用32个二进制位表示逻辑地址,页面大小为取2^12B = 4096B = 4KB。

如:逻辑地址2,用二进制表示00000000 00000000 00000000 00000010,前20位二进制对应的十进制值就是逻辑地址2对应的页号,即0号页,而后12二进制位对应的十进制值就是偏移量。如果0号页在内存中的起始地址为X,那么逻辑地址2对应的物理地址就是 X + 0000 00000010

同理,逻辑地址4097,用二进制表示00000000 00000000 00010000 00000001,前20位二进制对应的十进制值就是逻辑地址4097对应的页号,即1号页,而后12二进制位对应的十进制值就是偏移量。如果0号页在内存中的起始地址为Y,那么逻辑地址4097对应的物理地址就是 Y + 0000 00000001

结论:如果每个页面的大小为2KB,用二进制表示逻辑地址,则末尾的K位表示页内偏移量,其余部分就是页号

因此,如果让每个页面的大小为2的整数次幂,计算机就可以很方便的得出一个逻辑地址对应的页号和页内偏移量。

如果一个页面的大小为2KB,那分页存储管理的逻辑地址结构为:

地址结构包括两个部分:前一个部分表示页号,后一个部分表示页内偏移量W。

如果有k位表示“页内偏移量”,则说明该系统中一个页面的大小是2^k个内存单元

如果有M位表示“页号”,则说明在该系统中,一个进程最多允许有2^M个页面

 

四、页表

在知道如何计算页号和偏移量后,要计算实际的物理地址,还需要知道页号在内存中的起始地址,如何知道每个页面在内存中存放的位置,操作系统要为每个进程建立一张页表

  1. 一个进程对应一张页表
  2. 进程的每一页对应一个页表项
  3. 每个页表项由页号和块号组成
  4. 页表记录进程页面和实际存放的内存块之间的对应关系
  5. 每个页表项的长度都是相同的,页号是隐含的(下小节)

 

为什么每个页表项的长度是相同的,而页号是隐含的?

例:假设某系统物理内存大小为4GB,页面大小为4KB,则每个页表项至少应该为多少字节?

4GB = 2^32B,4KB = 2^12B

因此4GB的内存总共会被分为2^32 / 2^12 = 2^20个内存块,因此内存块号的范围应该是0~2^20-1

因此至少要20个二进制位才能表示这么多内存块号,因此至少要3个字节才够

(每个字节8个二进制位,3个字节共24个二进制位)

各页表项会按顺序连续地存放在内存中
如果该页表在内存中存放的地址为X,则M号页对应的页表项存放的地址为:X + 3*M

因此,页表的“页号”可以是“隐含”的。
只需要知道页表存放的起始地址页表项长度,即可找到各个页号对应的页表项存放的位置,找到位置后就可以读取该位置的值,即实际内存块号

在本例中,一个页表项占3B,如果进程由n个页面,则该进程的页表总共会占3*n个字节
 

五、小结

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烟敛寒林o

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值