虚拟内存映射的分页机制:使用一级页表
虚拟内存映射的分页机制:使用一级页表
提前熟悉 核心 关键词 的含义:
内存
内存页面
虚拟地址
物理地址
页面页码
页偏移
页表数组
高位,低位
总结:
目的:
通过给的虚拟地址(一个32位数字) 来求出 物理地址(一个32位数字)
需要借助的媒介:已经算好的 页表数组。数组元素代表 目标物理地址所在的 内存页面页码。可通过数组下标 读取页表数组的信息。
其中内存 是分页的,也就是他在 类似于一本书 一样的 一页中,而且在这一页中的 某个位置。物理地址具有两个重要的信息,
1物理地址 在页码为某个数字的 物理页面上。
2物理地址 在 当前页面 具有一个 偏移。
因此只要 求出 物理地址 所在的内存的 页面和页内偏移 这两个信息,就可以知道 物理地址的具体数字大小。
1.虚拟地址->页表转换->物理地址
2.页表数组是根据分配与需要,已经算好了的一个数组,可以直接读取使用。
页表数组 储存 某个 物理地址 所在的 内存页面的 页码。
页表数组 下表为 k的 元素 储存的信息是 物理地址 所在的 页面页码。
其中下表k 与 虚拟地址的 高20位 是一样的。
页表数组 书面定义:
它包含 2^20 = 1M 个元素,每个元素的值为页面编号(也就是位于第几个页面),长度为4字节,整个数组共占用4MB的内存空间。这样的数组就称为页表(Page Table),它记录了地址空间中所有页的编号。
页表数组元素高20位:表示页面编号
页表数组元素低12位:表示 当前页的相关属性,例如是否有读写权限、是否已经分配物理内存、是否被换出到硬盘等。**
- 虚拟地址是个32位的数字,这32位数字的意义
其实这32位数包含 页表的 的信息,还包含 页内偏移的信息
高20位: 页表数组 下标:
低12位:页内偏移(这个页就是虚拟地址的高20位这个数字作为页表数组的下表,对应的页表 )
4.物理地址的特征: 分页机制,也就是 所有的物理地址 是一页一页的,每页都有 页码,而且每页具有相同数量的地址,或者说每页大小一样。
书面说法:
分页(Paging)的思想是指把地址空间人为地分成大小相等(并且固定)的若干份,这样的一份称为一页,就像一本书由很多页面组成,每个页面的大小相等。如此,就能够以页为单位对内存进行换入换出:
当程序运行时,只需要将必要的数据从磁盘读取到内存,暂时用不到的数据先留在磁盘中,什么时候用到什么时候读取。
当物理内存不足时,只需要将原来程序的部分数据写入磁盘,腾出足够的空间即可,不用把整个程序都写入磁盘。
5 虚拟地址高20位作为 页表数组 下表,则 通过这个下标 找到 目标物理地址 所在 内存页面的 页码。
虚拟地址低12位 是 目标物理地址 在其所在 内存页面内 的偏移。
因此
a.虚拟地址高20位k做下标-> 页表数组a[]->在页表数组a[] 找到 目标物理地址所在 下标为k的 内存页码q( q为 页表数组元素 a[k]的 高20位 )
b.虚拟地址低12位p-> 目标物理地址 在其所在 内存页面内 的偏移p。
c.假设每页有n_page个地址,那么物理地址为 a[k] * n_page + p
其中虚拟地址 为 kp(连续数字,k为高20位,p为低12位)
页表数组元素高20位:表示页面编号
页表数组元素低12位:表示 当前页的相关属性,例如是否有读写权限、是否已经分配物理内存、是否被换出到硬盘等。**
注意,表示页面编号只需要 20 位,而页表数组的每个元素的长度却为 4 字节,即 32 位,多出 32 - 20 = 12 位。这 12 位也有很大的用处,可以用来表示当前页的相关属性,例如是否有读写权限、是否已经分配物理内存、是否被换出到硬盘等。
上面为原创,以下为转载自
http://c.biancheng.net/view/vip_2095.htmli
,维权联系,侵删。
既然内存是分页的,只要我们能够定位到数据所在的页,以及它在页内的偏移(也就是距离页开头的字节数),就能够转换为物理地址。例如,一个 int 类型的值保存在第 12 页,页内偏移为 240,那么对应的物理地址就是 2^12 * 12 + 240 = 49392。
2^12 为一个页的大小,也就是4K。
虚拟地址空间大小为 4GB,总共包含 2^32 / 2^12 = 2^20 = 1K * 1K = 1M = 1048576 个页面,我们可以定义一个这样的数组:它包含 2^20 = 1M 个元素,每个元素的值为页面编号(也就是位于第几个页面),长度为4字节,整个数组共占用4MB的内存空间。这样的数组就称为页表(Page Table),它记录了地址空间中所有页的编号。
为什么要这样切割呢?因为页表数组共有 2^20 = 1M 个元素,使用虚拟地址的高20位作为下标,正好能够访问数组中的所有元素;并且,一个页面的大小为 2^12 = 4KB,使用虚拟地址的低12位恰好能够表示所有偏移。
注意,表示页面编号只需要 20 位,而页表数组的每个元素的长度却为 4 字节,即 32 位,多出 32 - 20 = 12 位。这 12 位也有很大的用处,可以用来表示当前页的相关属性,例如是否有读写权限、是否已经分配物理内存、是否被换出到硬盘等。
例如一个虚拟地址 0XA010BA01,它的高20位是 0XA010B,所以需要访问页表数组的第 0XA010B 个元素,才能找到数据所在的物理页面。假设页表数组第 0XA010B 个元素的值为 0X0F70AAA0,它的高20位为 0X0F70A,那么就可以确定数据位于第 0X0F70A 个物理页面。再来看虚拟地址,它的低12位是 0XA01,所以页内偏移也是 0XA01。有了页面索引和页内偏移,就可以算出物理地址了。经过计算,最终的物理地址为 0X0F70A * 2^12 + 0XA01 = 0X0F70A000 + 0XA01 = 0X0F70AA01。
这种思路所形成的映射关系如下图所示:
可以发现,有的页被映射到物理内存,有的被映射到硬盘,不同的映射方式可以由页表数组元素的低12位来控制。
使用这种方案,不管程序占用多大的内存,都要为页表数组分配4M的内存空间(页表数组也必须放在物理内存中),因为虚拟地址空间中的高1G或2G是被系统占用的,必须保证较大的数组下标有效。
现在硬件很便宜了,内存容量大了,很多电脑都配备4G或8G的内存,页表数组占用4M内存或许不觉得多,但在32位系统刚刚发布的时候,内存还是很紧缺的资源,很多电脑才配备100M甚至几十兆的内存,4M内存就显得有点大了,所以还得对上面的方案进行改进,压缩页表数组所占用的内存。