《操作系统 - 清华大学》4 -2:非连续内存分配:分页
文章目录
- 1. 概述
- 2. 页的寻址
- 3. 帧
- 4. 页
- 5. 页寻址机制
1. 概述
前面把段机制做了简单介绍,段机制相对而言在现有的 CPU 硬件环境中是属于比较少的,现在绝大部分 CPU 主要采取的是分页机制。这是另外一种和分段机制不同的硬件的非连续内存的管理方式,这里面主要两部分,一个是基于页的寻址,基于页的地址空间,以及基于分页机制的硬件实现方式,这两部分的内容。
2. 页的寻址
首先看页的寻址,需要比较一下,前面讲用分段机制,首先需要知道段号以及段内的偏移,那其实分页也是一样的,它也需要页号和页内的偏移,那它和刚才说的分段有什么区别,其实区别主要在于偏移,在分段机制里面,段的尺寸是可变的,而在分页里面页帧的大小或者页的大小其实是固定不变的,这是它们最大的区别,就这个区别。
那可以看到,可以说把页或者页帧分成不同的类,可以按照2的幂次方来分,主要是 512 字节或者4K 或者8K,同时逻辑页和物理页的大小是一样的,比如说定成4K都是4K,要定成8K都要是8K,这样是便于硬件去对它做相应的实现。同时这里面需要注意一下,页帧 frame 是物理页, page 代表逻辑页,那需要建立逻辑页地址和物理页地址映射关系。
那这个映射关系里面需要用到什么呢?
硬件机制中页表, MMU 内存管理单元,这属于硬件中的组成,CPU 中的重要组成部分。这里面还有TLB,就是块表来完成对页表的缓存,当然这些在后面会逐一做讲解,有了这些机制之后,其实可以加速地址转换。
3. 帧
叶帧(frame)是指物理内存的组织和布局方式。很明显页帧代表物理内存的地址是有两部分组成,第一个是页帧号 frame number,第二个是页帧里面的偏移 offset,比如一个物理地址有 n 位,其实它分两块了,它的页帧号占了 F 位,页帧本身的大小占 S 位,也就确定了在整个寻址空间中有
2
F
2^F
2F 页帧个数,同时有
2
S
2^S
2S的每一页大小,所以说对于物理地址而言,如果知道它的页帧号和页帧偏移,那可以得出它的物理地址,就下面的公式所示: 物理地址 =
2
S
2^S
2S *f + o,这个地址就是它的物理地址。那上面这幅图也可以很清楚地看出来。这里面有两部分组成,一个是页帧的 offset,一个是页帧的帧号,有了它们之后,就可以迅速地对应到页帧号和叶帧 offset 到底是指向哪一个物理层单元。
结合示例,来理解页帧设计,比如现在有16位 物理地址空间,在这里每个页帧的大小是512字节,也意味着页 offset 一共有 2 9 2^9 29,512字节,如果说给出一个地址,这个物理地址的页帧号是3,页帧内偏移是6。问它具体的物理地址的位置是多少?这个位置其实就是1542,那这个值怎么算出来的?
~
整个地址空间由16 bit 组成,其中 9 bit 表示页帧内的偏移,剩下 7 bit 表示页帧号的大小,根据前面公式,物理地址= 2 S 2^S 2S
*f + o = 2 9 2^9 29 *3 + 6 = 1542 ,看上右图,具体绿色那块区域的位置。
4. 页
看看逻辑地址寻址方式,这时候用页(page)来表示。其实它的计算方式和页帧是很类似的,可以说计算方法是一样的,那区别在什么地方?区别在于页号 size 和页帧号 size 可能不一样,但是它的 offset(page offset size),就是它每页的大小和每个页帧大小这两个是一样的,大家需要注意这个区别。如果把它的业号用 p 表示,业内偏移也用 o 来表示,那么也可以用公式简单地表示页的逻辑地址 =
2
S
2^S
2S * p + o,S代表一个页的 size, P 代表有多少个页。 所以 P 和前面 F 可以不一样,但计算方法其实是一样的,从这种方式可以得出有相应页号和相应页内偏移的逻辑地址,它对应的实际的逻辑地址是多少。
5. 页寻址机制
以上得出基于逻辑页寻址表示,有这个表示之后,看看怎么来完成地址转换。
从上图左边开始看,当一个程序要运行的时候,这个程序本身逻辑地址是连续的地址空间,而且是由一页一页组成,每页大小是一样的,但整个这个程序的容量和物理地址空间可能不一样。比如说可能程序占很大地址空间,但物理空间可能没有这么大。
-
看看怎么来完成映射
首先程序要执行的时候,与分段映射机制也是类似的,程序运行时候 CPU 会去寻址,无论是执行一条指令,还是说访问数据,它都需要知道指令或者数据所在位置。寻址就需要知道这个地址,地址是逻辑地址或虚拟地址,虚拟地址是由 CPU 下面的那个图来表示的,可以看到这个地址分了两块,一块是页内偏移offset,o表示,另一块是页号,p 表示,首先关注页号,把页号作为 index,查 pagetable。简单理解 pagetable 存的是以页号为索引对应的那一项的内容,放帧号(frame number)。
一旦知道页号,就可以查出来对应的帧号是多少,实际上就是大的数组,这个数组用 page table 来表示,那同时也要知道,如果要去查 page table 的话,需要知道从哪开始查,所以还需要有很重要的信息 page table 的base,基地址在什么地方,有了 base 和 page number (做 index 可以查找对应页表项的内容)。
通过页号知道帧号,这个很关键,知道帧号之后,帧号再加上 offset,形成页帧号和页帧 offset 共同组成的物理地址,知道物理地址之后,找到物理地址所在的位置,真是整个大致的计算过程。
-
需要注意这个 page table 谁来建立
page table其实应该是由操作系统来建立,建立好 page table 之后,才能够让程序正常地完成映射关系,才能正常地跑,所以 page table 是由操作系统在初始化的时候,在分页机制的时候就需要建立好,建立好之后就能够让程序正常的跑起来。
注意分页机制一些不同的地方:
- 它和分段机制有点不一样,分页机制的页内偏移大小是固定的,使得在硬件管理上面可以更加简洁的方式来实现,不像分段方式需要考虑不同段的大小是不一致的问题。
- 第二个需要注意,整个逻辑页地址空间的大小和以帧组成的物理地址空间的大小不一致,一般而言,逻辑地址空间要大于物理地址空间。这会存在问题,逻辑地址空间的内容,物理空间没法全都装得下,怎么办?后面虚拟内存的时候做讲解,这里暂时把问题放一放。
- 逻辑地址空间是连续的,连续的寻址,映射到物理空间之后,它不一定连续了,它有可能分散在不同物理空间的页帧中,那这样带来的好处是有助于减少碎片。