操作系统内存管理
分页储存
基本概念
重要数据结构--页表
1、每个页表项占用多少字节?
Eg:假设某系统物理内存大小为,页面大小为,则每个页表项至少应该为多少字节?
由题目可知,
又因为
所以的内存总共会被分为个内存块
所以内存块号的范围应该是 ~
又因为一位二进制可以表示的状态有种
所以全部的内存块号至少要用来表示
又由于计算机分配内存是以字节(B)为单位分配,因此需要将位(bit)转化位字节
所以至少需要来表示块号
又由于页表项另外一个组成:页号不占用存储空间(见下面解释),
因此一条页表项的大小只有块号做贡献,即 ,而上例中整个页表有个页表项,故存储整个页表至少需要
另外,
重要考点:由计算机中内存块的数量推算出页表项中块号至少占用多少字节
由于页表中的页表项是连续存放的,因此页号可以是隐含的,不需要占用空间。可以类比数组,数组在内存中只存放数据,并不会单独的存放多一个下标号。
1.1、如何根据页号找到(在内存中)对应的页表项(的地址)
这里需要注意的一点是,页表中的块号所记录的只是内存块号,而非内存块的起始地址。
J号内存块的起始地址为: J * 内存块大小
但是当我们将页表项按照上个例题所给的条件存放在内存时:一个页面为,一个页表项大小为,则每个页框可以存放(序号从0开始,即存放0~1364号页表项)个页表项,但是这个页表框会剩余 页内碎片,又由于一个页表项是连续存放的,不能分开存放在不同的页框中,所以下一个页表项第1365只能存放在下一个页框中,而不能填补上一个页框的1B页内碎片。
因此,1365号页表项存放的地址为:X+3*1365 +1。此时可以看出,由于页表项之间并没有连续存放,所以上面的公式X+3*I
失效。
但是如果我们将页表项的占用大小改成4B的话,则每个页框刚好可以存放1024个页表项,1024号页表项虽然是存放在下一个页框中的,但是它的地址依然可以用 得出,因为每个页框都刚好可以被填满,不存在页内碎片,即页表项之间连续存放。
结论:理论上,页表长度为即可表示内存块号的范围,但是,为了方便页表的查询,常常会让一个页表项占用更多的字节,使得每个页面恰好可以装得下整数个页表项
2、如何实现从逻辑地址到物理地址的转换
由分页的特点:用于存放进程的页框是离散存储的,但是页框内部是连续存放的。所以我们可以先找到该页框的起始地址,然后再加上框内的偏移量即可求得具体的物理地址,具体的:
假如要访问逻辑地址A,则
- 确定逻辑地址对应的“页号” P
- 找到P号页面在内存中的起始地址(需要查页表,起始地址为: 内存块号 * 内存块大小”)
- 确定逻辑地址A的“页内偏移量”W
- 最后逻辑地址A所对应的物理地址 = P号页面在内存中的起始地址 + 页内偏移量W
举例说明:
如何将 将逻辑地址拆分成页号与页内偏移量。
在某计算机系统中,页面大小是。某进程逻辑地址空间大小为,则逻辑地址对应的页号、页内偏移量是多少?
由题目所给,可以将进程逻辑地址空间分成下图:
由上图不能看出:
页号 = 逻辑地址 / 页面长度 (取除法的整数部分)
页内偏移量 = 逻辑地址 % 页面长度(取除法的余数部分)
因此例子中所给的逻辑地址110
页号P = 100 / 50 = 2
页内偏移量W = 100 %50 = 10
因此物理地址为 =
2.1 二进制的逻辑结构的地址划分
在计算机内部,地址是用二进制表示的,如果页面大小刚好是2的整数幂,则计算机硬件可以很快速的把逻辑地址拆分成(页号,页内偏移量)
逻辑地址结构(假设操作系统用32个二进制来表示逻辑地址):
31 ................. 12 | 11 ................. 0 |
---|---|
页号P | 页内偏移量W |
地址结构包含两部分:前一部分为页号P,后一部分位页内偏移量W。如果每个页面大小位,用二进制表示逻辑地址,则末尾k位即为页内偏移量,其余部分就是页号。
- 如果由K位表示“页内偏移量“,则说明系统中一个页面的大小是2K个内存单元”
- 如果由M位表示“页号“,则说明系统中,一个进程最多允许有2M个页面,即,页号范围为 :0 ~ 2M-1
如上表中,地址长度为32位, ~位为“页内偏移量”,或称“页内地址” ,可知页面大小为: ;~为页号。
因此,可以将十进制的页号与页内偏移量单独的转换成二进制的表示形式,然后将将其拼接:
举例说明:
假设某计算机用32个二进制表示逻辑地址,页面大小为 (结构划分与上表单一致)
如,逻辑地址 转化:
页号 = 转化为长度占20
位的二进制形式为:00000000000000000001
页内偏移量 = 转化为长度占12
位的二进制形式位:000000000001
然后将将其拼接得到二进制形式的逻辑地址: = 00000000000000000001000000000001
同理,如果内存块的大小刚好也是2的整数次幂的话,该方法也适用。
3、总结
两级页表
1、单级别页表存在的问题
由上面的如何根据页号找到对应的页表项中可以得知,该方法适用于条件为,所有页表项必须为连续存放在内存中。
现在考虑这么一个问题:
某计算机系统按字节寻址,支持32位的逻辑地址,采用分页储存管理,页面大小为,页表长度为,则将全部页表项连续储存需要多少连续的页框?
,然后 ,可以看出,页框大小刚好是页表项的整数倍,所以页表项在内存中的存放可以是连续的。另外,页内地址要用12位表示,剩余20位表示页号,因此,该系统中一个进程最多有页,这也是页表项的数量。而一个页表项大小位,故一个页表所占的总大小(即全部页表项的大小总和)为: ,将这些页表项连续分框装进内存块时,所需的页框数量为: ,因此当页表很大时,需要占用很多个连续的页框。
1.2、二级页面表定义
这时我们可以尝试对页面进行分页:
单独的对页表的分页生成一个页表进行进行映射:页目录表
1.3、二级页表的地址转换
2.1、几个需要注意的细节
- 若采用多级页表机制,则各级页表的大小不能超过一个页面,
-
两级页表的访存次数分析(假设没有快表机构)
- 第一次访存:访问内存中的页表目录表
- 第二次访存:访问内存中的二级页表
- 第三次访存:访问目标内存单元
总结:N级页表的访存次数为: 次
3、总结
课后例题
-
某计算机主存按字节编址,采用二级分页储存管理,地址结构如下:
页目录号(10位) 页号(10位) 页内偏移量(12位) 则 虚拟地址 对应的 页目录号、页号分别是()()
题目给出的逻辑地址是十六进制的,我们需要将其转化为二进制高位补零,然后将其与地址结构进行对比划分 前10位、11~20位、21~32位分别对应:页目录号,页号,页内偏移量 <-高位 低位-> 2 0 5 0 1 2 2 5 / \ / \ / \ / \ / \ / \ / \ / \ 0010 0000 0101 0000 0001 0010 0010 0101 |------页目录号-----|---------页号-------| 0010 0000 01 01 0000 0001 对两个二进制重新从低位开始编排(四个一组): 00 1000 0001 01 0000 0001 高位补零: 0000 1000 0001 0001 0000 0001 页目录号 = 0000 1000 0001 页号 = 0001 0000 0001
-
某计算机主存按字节编址,逻辑地址和物理地址都是32位,页表项大小为4B。
如果其使用的分页存储管理方式,且其地址结构位:
页号(20位) | 页内偏移量(12位) |
---|---|
问:一个代码段的起始逻辑地址为 ,其长度为 ,被装载到物理地址从 开始的连续主存空间中。页表从主存中物理地址 开始处处连续存放,如下图(地址大小自下向上递增)。请计算出该代码段对应的两个页表项的物理地址、这两个页表项中的页框号,以及代码页面2的起始物理地址。
【解】
由逻辑结构可知,前20位为页号,将代码段起始逻辑地址转化为二进制,其前二十位下划线的为页号:
= 0000 0000 0000 0000 1000 0000 0000 0000
=> 页号 = 0000 0000 0000 0000 1000 = 8
因此可得知逻辑代码段的起始对应页表的八号页表 ,于是根据公式I号页表项的物理地址=页表始址+I*每个页表项大小
。
=> = + =
由于两个相邻的页表项地址之间只相差一个页表项的大小,
=> = =
由于页框号对应的是物理块号,因此我们可以借助用物理块的物理地址求得的物理块号从而逆推页框号。
代码页面1所对应的物理块号为 ,同时也是页框号1
要求页框号2,得先求得代码页面2的物理地址。
由于两个相邻的物理块地址之间只相差一个页框大小 (),
=> = $
与处理页框号1步骤相同,可求得页框号2 =
参考:1、22考研·操作系统全程班;2、2021年操作系统考研复习指导
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了