欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

内存分页

程序员文章站 2022-05-29 07:53:31
...

为什么要内存分页

假设我们以程序为单位,把程序运行所需要的虚拟空间映射到物理空间。

程序A 需要100M内存 虚拟地址的范围是从 0X00000000 到 0X06400000 映射物理地址 0X00C00000 到 0X07000000
内存分页
可以实现地址隔离 且程序可以使用固定内存地址,但是当物理内存不足的时候

就会将整个程序进行 换入换出到磁盘 会严重影响运行速度 并且由于是将整个
程序做为映射,所有在物理内存上需要连续的内存空间。降低内存的使用效率

内存分页

程序运行时,只要小部分的数据是被频繁用到的,很多数据在一个时间段内不会被用到,以整个程序作为映射会将暂时用不到的数据从磁盘中读取到内存,也会将过多的数据一次性写入磁盘,这会严重降低程序的运行效率。

现代计算机都使用分页(Paging)的方式对虚拟地址空间和物理地址空间进行分割和映射,以减小换入换出的粒度,提高程序运行效率。

概念:将地址空间分出等分大小,一样的一份就叫一页。

  • 程序运行时:将必要的数据从磁盘读取到内存,暂时用不到的数据先留在磁盘中,什么时候用到什么时候读取。
  • 物理内存不足时:将原来程序的部分数据写入磁盘,腾出足够的空间即可,不用把整个程序都写入磁盘。

页的大小

页的大小一般都为4kb,假设pc机为32位,虚拟内存地址空间为4GB,则有
2^32/1024/4 = 1048576个页,物理内存也是这样的分法

分页机制的实现

现代操作系统都使用分页机制来管理内存,使得每个程序都有自己的地址空间,当程序使用虚拟地址的时候,都必须转为实际的物理地址,才能真正的在物理内存上定位数据。内存地址的转换是通过页表来实现的。
内存分页

直接使用数组转换

如果直接用数组来转换,一个数组元素保存一个物理地址,而虚拟地址作为数组的下标,这样就可以很简单的实现映射,并且效率不低。
内存分页
但是一个地址4字节(32位系统中),整个数组的大小为2^32 * 4 = 16G,这要占用16G的内存显然不现实。

一级页表

页的大小固定,因此只要知道数据的页号和在页中的偏移量(距页的第一个字节的距离)就可以找到数据的物理地址。
例如,一个 int 类型的值保存在第 12 页,页内偏移为 240,那么对应的物理地址就是 2 ^12 * 12 + 240 = 49392。(以字节为单位)相当于内存中的第49392字节

建立页表:
虚拟地址空间大小4G ,总共有2 ^32 / 4 * 1024 = 1049392 = 2 ^20个页面
定义一个数组一共2 ^ 20个元素,每个元素为页面编号(即第几页),大小为4字节,这样整个数组大小为 2 ^ 20 /1024/1024*4 = 4M 这个数组就叫做页表。

数组元素的大小为4字节,32位,前20位表示页面编号,后12位表示当前页的相关属性:是否有读写权限、是否已经分配物理内存、是否被换出到硬盘等。

内存分页
虚拟地址的大小也为4字节,高20位作为页表数组的下标(可以得到数组元素对应的页码),低20位作为页内偏移 2^12/1024 刚好等于每页的大小4k。

例如一个虚拟地址 0XA010BA01,它的高20位是 0XA010B,所以需要访问页表数组的第 0XA010B 个元素,才能找到数据所在的物理页面。假设页表数组第 0XA010B 个元素的值为 0X0F70AAA0,它的高20位为 0X0F70A,那么就可以确定数据位于第 0X0F70A 个物理页面。再来看虚拟地址,它的低12位是 0XA01,所以页内偏移也是 0XA01。有了页面索引和页内偏移,就可以算出物理地址了。经过计算,最终的物理地址为 0X0F70A * 2^12 + 0XA01 = 0X0F70A000 + 0XA01 = 0X0F70AA01。

如过想缩小页表的内存可以使用二级页表 多级页表

MMU

在cpu内部,有一个部件叫做MMU(Memory Management Unit,内存管理单元),由它来负责将虚拟地址映射为物理地址
内存分页
cpu发出的是虚拟地址,这个地址交给MMU,经过转换变成物理地址。在MMU内部有个缓存,存储了页目录和页表。

MMU 只是通过页表来完成虚拟地址到物理地址的映射,但不会构建页表,构建页表是操作系统的任务。在程序加载到内存以及程序运行过程中,操作系统会不断更新程序对应的页表,并将页目录的物理地址保存到 CR3 寄存器。MMU 向缓存中加载页表时,会根据 CR3 寄存器找到页目录,再找到页表,最终通过软件和硬件的结合来完成内存映射。

MMU 除了能够完成虚拟地址到物理地址的映射,还能够对内存权限进行控制。
操作系统在构建页表时将内存权限定义好,当MMU对虚拟地址进行映射时,首先检查低12位,看当前程序是否有权限使用,如果有,就完成映射,如果没有,就产生一个异常,并交给操作系统处理。操作系统在处理这种内存错误时一般比较粗暴,会直接终止程序的执行。

相关标签: 内存