在Linux内核管理中,MMU的页表查询是最基础的知识,这里目的是通过理解页表查询过程,去厘清页表、页表项、页面、页面偏移量(也称页内偏移量)等概念及它们之间的关系,为Linux内核管理的学习与使用奠定基础。
接下来这里用最简单的一级页表查询过程来说明,理解了一级页表的查询过程,那么二级页表查询、三级页表查询也就能依次类推了。
前提条件:
以32位宽的处理器(虚拟地址和物理地址均是32位位宽)、页面大小4KB为前提讲解。
前提条件的分析:
1.寻址空间大小的由来:
由于是32位位宽,所以寻址空间大小是4GB,怎么计算来的呢?
32位—>则可以知道一共有2^32个地址,会有地址0x0000 0000、0x0000 0001、0x0000 0002…0xffff ffff,每个相邻地址间都只相差一个字节(1Byte),那是因为arm是以单个字节为单位寻址的,其他变量类型只是单个字节char类型的变种。所以2^32*1Byte = 4GB(地址个数 * 每个地址占1Byte大小 = 总的寻址空间大小),即寻址空间大小。
2.页面大小
前提条件里说页面大小4KB,这个其实是指物理页面大小,这个大小是由.s文件里设定的,也可以设定为16KB、64KB等等,一开始就设定了,设定好后,后面的页表大小才能确定,这里就以经典的4KB大小来说明。
一级页表查询
基于上述前提条件,一级页表查询过程如下图:
根据上图,我们先理解:
1.虚拟地址的VA[11:0]:称为页面偏移量,因为物理页面大小是4KB,所以一个物理页面内有2^12 个地址,即页面内偏移量是0- - -2^12,需要占用12位;
2.虚拟地址的VPN[31:12]:称为虚拟页帧号,它代表在页表中的偏移量,页表的基地址加上VPN(页表中的偏移量),就得到了页表中具体页表项的地址;
3.有效位:单个页表项中的一个属性位v,表示页表项的属性,v=0表示对应物理页面不存在内存中;v=1表示对应的物理页面存在内存中。
由上图我们可以知道:
查询一个虚拟地址对应的物理地址的过程如下:
虚拟地址的VPN作为索引(偏移量) + 页表基地址(即页表的起始地址,存放在页表基地址寄存器) = 页表中具体某一个页表项的地址
—>
找到页表项地址后,读取出该页表项里存放的PFN,即拿到PFN(物理页面的基地址,即页面起始地址)
—>
物理地址的PFN作为页面基地址(即页面起始地址,也称页帧号) + 虚拟地址的VA(即页面内偏移量,也就是等价于PA) = 物理地址
页表、页表项、页面间的概念与关系:
页表:由所有页表项组成;
页表项:一个页表项占用4个字节(因为是32位宽,所以这里一个页表项占4个字节),一个页表项里面存储了一个PFN(物理页面在内存中的帧号,也即物理页面的基地址);
页面:这个是指物理页面,物理内存中把内存分成一个个页面,每个页面大小一样;
我们来看看,4GB物理内存,页面大小4KB时,为了能映射整个4GB物理地址空间,需要多大的页表来存储VPN到PFN的映射关系呢?页表中总共有多少页表项呢?
4GB(总的物理内存大小) / 4KB(每个页面大小) = 2^20 个页面;
一个页面就有一个页面基地址- -PFN(页面的起始地址,也称页帧号),一个页表项存储一个PFN信息,那么就一共有2^20 个页表项;
2^20(页表项个数) * 4Byte(一个页表项占空间大小,4字节) = 2^20 * 2^2 B= 4M;
所以,页表大小4M,由2^20个页表项组成。而页表项地址如上面查询过程所提,一个页表项地址对应一个VPN索引值(偏移量),所以要表示 2^20个索引值(偏移量),需要20位,即VPN占虚拟地址的位数(31:12,20位)。