[操作系统概念]第六部分——内存管理(2):分页分段

分页

分页是指,将逻辑地址分成固定大小的块,每一块成为一页,对应的物理地址按同样大小分块,成为帧。此外,系统还需要硬件支持称为 “页表” 用于充当索引的功能,因为CPU每次生成的地址并不对应内存地址,而是一个包含页号和页偏移两部分的地址,页号在页表中映射到一个表示物理的基地址,基地址+页偏移后才是真实的物理地址。 分页不会产生外部碎片,但是还会产生内部碎片。
页表硬件

分页模型

页大小及地址空间

页的大小(和帧一样)和硬件有关,一般为2的幂次,范围为512B~16MB不等,这样容易将逻辑地址分成页偏移和页号,如果页大小是2的m次幂,则页偏移是CPU产生的逻辑地址的后m位,剩余位为页号。页大小太大了内部碎片增多不好,但是太小了I/O操作又会增多,通常设为4~8KB。

使用分页的额外问题

使用分页,意味着内存在用户视角和操作系统视角的分离,用户看到的逻辑内存是连续的,但是操作系统将逻辑地址映射到物理地址之后确实离散的,这样在管理时有几个问题。
1. 操作系统必须知道物理内存中帧的使用情况,这需要操作系统维护一个成为“帧表”的数据结构,来标记物理内存中每一个帧的使用情况,是否占用,被哪个进程的哪个页占用?防止对物理地址的冲突使用。
2. 大部分操作系统中每一个进程都有自己的页表,页表也存放在进程控制块中。
3. 内存保护问题,防止对只读的内存进行写操作,这样的保护是通过在页表中增加保护位来实现的。此外对无效内存的访问问题也是页表需要考虑的,如果页是无效的,说明页不在进程的逻辑空间中,这可以通过一个有效-无效位来保证。但是,如前所述,分页技术存在内部碎片,尽管一个页是有效的,页内也可能存在无效的内存区间,对于这个问题,有些系统还提供 页表长度寄存器(PTLR) 用于计算每个逻辑地址是否在进程的有效范围内。
4. 对于多用户系统,很可能多个用户运行同一个程序,那么这些程序代表的不同进程的代码段内存其实是可以公用的,这种公用可以通过页表来实现。这里需要注意的是,可以公用的代码段应当是 可重入代码 ,它们不能在执行时发生改变。这样每个进程使用私有的寄存器和堆栈保存数据,同时使用共有的代码段可以节省空间。这样使用的页成为共享页。

页表的硬件实现

因为CPU每一次访存都需要经过页表,所以页表一定要快。所以很容易想到使用寄存器,如果页表较小的话使用一组寄存器是很好的选择。但是如果页表较大,寄存器放不下怎么办?还要使用内存,然后使用 页表基寄存器(PTBR) 指向内存中的页表,但是这样会导致一条地址指令两次访存,而且速度不快,解决方式是加缓存。通过使用 转换表缓冲区(TLB) ,一种特殊的硬件缓存,缓存一部分页表。使用TLB后,访问页表的问题就变成了缓存失效问题。
缓存失效的解决方法很多,从最近最少使用替换到随机替换,此外,一些TLB还提供固定条目不替换的功能和区分进程(使用地址空间标识符)的功能。需要注意,页表是和进程相关联的,如果CPU调度下一个进程,当前的页表需要更换,同样TLB也要刷新(但是使用地址空间标识符的话,可以通过区别进程的方式避免刷新)。

页表结构(多种页表类型)

  1. 层次页表(向前映射页表):如果内存空间过大,那么页表也会很大,一整个页表不方便连续存储,层次页表用来解决这个问题。在使用分页逻辑地址的基础上,将页号分成多个。也就是说,一个逻辑地址的两部分页号和页偏移,页号部分包含多个页号,而不是一个。这样,页表也对应有若干个(和页号个数相同),使用页号1通过页表1找到下一个页表(页表2)的地址,然后使用页号2(P2)在页表2中找到下一个页表(页表3)的地址…………直到找到最终的帧地址,结合逻辑地址的页偏移得到物理地址。注意,这其中,多个页表是通过指针联系在一起的,也就说,页表可以离散存放。
    层次页表
  2. 哈希页表:对于超出32位的地址空间,常使用哈希页表,哈希页表使用链表法(哈希后产生相同值的项放到一个链表中),对于CPU产生的地址,还是先找页号,页号通过哈希函数在哈希页表中找到条目的一个链表,然后遍历链表,比较页号是否与链表中的项的第一个域匹配,匹配的话,用第二个域代表帧号,CPU产生地址的页偏移还作为物理地址的偏移量。
    哈希页表
  3. 反向页表:由于每一个进程都有一个页表,每一个页表可能有很多项,传统的页表可能会占用很多空间。反向页表用于解决这个问题,反向页表的思路是为物理内存的每一个帧维护一个表,这样操作系统只需要维护一个页表即可。为了区分是哪个进程使用了哪一帧,CPU产生的逻辑地址会分成三部分——进程标识符、页号、页偏移。使用进程标识符和页号,搜索整个页表,计算帧号,结合页偏移得到物理地址。
    反向页表

分段

分页的一个问题是用户视角的内存和操作系统视角的内存是不一样的,分段从另一个角度解决内存不连续使用的问题。
分段将一个程序所需的内存空间分成代码、全局变量、堆栈等段,每一段占用一定的空间,一个进程拥有一个段表,其中有每一个段的段长度(界限)和基地址。CPU产生的逻辑地址分成段号和段内偏移,通过段号可以在段表中找到包含基地址和段长度的项,进而比较段内偏移是否超出界限,之后在找到物理地址。
分段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值