Q: 为什么使用多级页表能省内存?
A:
首先考虑一级页表的情况。
内存虚拟空间是0~4G
按4K一页的方式分页。
那么需要总共1024 * 1024个页表项, 即1M个页表项
其中每个页表项为32位整数。
为什么??
想想里面需要存放什么???
最主要的其实就是映射的页表基地址。
假设0x12345678的虚拟地址, 映射的物理地址是0x56789678。
那我们页表项主要记录的就是0x56789这个基地址!!
最后12位是页表的偏移地址/序列号。
所以页表项就至少需要20位的空间了...所以用32位也就好理解了...
ok, cpu寻址0x1234 5678这个虚拟地址, 首先找到 mmu页表的基地址, 这个在cp15协处理器寄存器中保存着。(当前进程 + 内核的页表)
由于有1024*1024 1M个32位页表项,
所以页表空间需要4M,
假设起始地址是0xC100 0000,
最大范围就是, 0xC140 0000,
所以我们基地址就是0xC1.....
ok, 我们取出了mmu页表基地址0xC1,
具体偏移呢?? 根据前20位, 即0x12345寻址。
找到页表项位置, 0xC10 8D14 (页表项4字节对齐, 所以最后两位是0)
假设寻找虚拟地址 0xFFF0 FFF0这个地址, 需要找第0xFFF0 F页表项。
0xFFF0 F * 4 = 0x3FFC3C (页表项最后两位为0, 即4字节对齐, 需左移两位, 也即乘以4)
则需要找到 0xC13F FC3C 这一页表项。
ok, 然后里面存放这物理地址页的基地址, 也即0x56789, 然后组合上页偏移地址, 就可以了。
最后寻址 0x56789678成功。
ok, 回归正题, 为什么二级页表比一级页表省内存?
从以上可以, 4k分页方式, 一级页表每一个页表项为4byte, 总共需要1M个页表项。
共需要内存4M。这样才能将0~4G的虚拟内存空间全部覆盖到。
否则 cpu 寻址未覆盖的 区域, 直接就寻址出错。 (像data abort和pre-fetch abort至少是寻址ok的, 取指出错)
比如汇编指令 ldr r0 0x12345678, 直接寻址就出错了...这个貌似不在arm的几种异常里面....
ok, 一级页表4M空间。
假设用段1M, 页4K的方式制作二级寻址页表。
首先为了0~4G空间全覆盖, 1024个段空间是不能省的。
而具体每个段对应的二级页表是否需要??
这个就不一定了....
通常我们写代码编译完 代码段 + 数据段也就是几百K 到几十M的范围。
假设我们写了段程序, 代码段 + 数据段 也就4M以内。
由于代码和数据的连续性,
所以我们可能也就只需要4个段就够了。。。
如此, 我们只需要将四个段的映射做好就可以了。
1个段对应256个页表。
所以我们4个段也就用1024个页表就够了。
最终, 这个进程使用的页表内存大小, 就为1024 * 4 + 1024 * 4,
即4K + 4K = 8K 就够了。
和一级页表比较下?
是否节省了很多内存??
是的, 奥妙就在这里^^
* 如果和我们书本写目录那样.... 那么 目录级别越多, 写得字肯定越多啦^^
因为书本每级目录都是全映射的...