zoukankan      html  css  js  c++  java
  • self-mapping page tables

    1. x86 10-10-12分页

      很久之前就听说过页表的自映射机制,但始终不是很理解。直到昨天读了《Windows内核原理与实现》中内存管理一章才明白了其设计的思想。所以准备记录下来自己的理解。

      首先我准备先从最简单的x86两级分页开始(x86 PAEx64分页准备以后在写),首先x86未开启PAE模式的情况下最大能够索引4GB大小的空间,由于是10-10-12分页,因此PDE有2^10项
    (1024),每个PDE又能索引2^10项(1024)个PTE,因此描述4GB大小的内存空间总共需要2^20个页表,又因为再此分页模式下每项占4个字节,所以总共需要4MB大小的空间来存放页表。


      Windows对页表的存储是在一块连续的4MB物理空间(且地址对齐),32位的Windows的PTE的起始线性地址恒在0xC0000000。由于这4M的页表描述了整个内存空间,而页表也属于这块物理内存的一部分,那么其中就肯定存在从某一项开始连续的1024项页表用来描述这4M的页表自身。如果我们将这1024项页表作为PDE,就节省了4K的PDE空间。实现了页目录表作为页表的复用。这就被称为页表自映射。


      每个页表能够描述4KB大小的内存,因此就引出了一个PFN(page frame number)的一个概念,整个内存可以用这个PFN来描述,同时这个PFN又是PTE的索引。PTE_base = 0xC0000000的
    pfn为PTE_base/0x1000 = 0xc0000,也就是说从PTE的0xC0000项开始的1024项索引自身。因为前面我们介绍了Windows的自映射机制,这里可以验证一下:
      1.我们可以通过Cr3读取PDT基地址
      2.PDT共1024项,每项可以索引1024个PTE,因此上面说的PTE的第0xC0000索引在PDT中为0xC0000/0x400 = 0x300项。
      3.因此预计的实验结果是:通过cr3访问PDT第0x300项的到的PTE地址指向cr3自身。
         

        通过上面实验我们可以清楚的看到Cr3的第0x300(+c00是因为每个PDT占4字节,0x300*4=0xc00)中存放的PTE为0x0039067,去掉最后12位的页表属性后为0x39000,正好是Cr3的值。验证了页表自映射的机制。我们知道Cr3中储存的第一个值就是PTE_base的物理地址,但是我们又不能直接对物理地址进行读写。所以当我们在Cr3中找到一项的值等于Cr3自身时(如上所说),我们将这一项的索引作为10-10-12分页的第一个10位索引进行左移22位的到的一个虚拟地址不就是指向PTE_base的虚拟地址了吗,如上所说,我们找到的索引22<<0x300 = 0xC0000000就是PTE_base的虚拟地址,因为我们读写的是虚拟地址,所以我们就可以根据这个PTE_base的虚拟地址操纵页表。

        当PDE的索引为0x300项时,这时PDT中存储的PTE地址指向PDE的起始,因此如果PTE的索引为0x300时,这时的PT的值为PDT的起始地址。因此(11000 00000)(11000 00000)(0000 0000 0000)这个虚拟地址就为PDE_base,即0xC0300000,即这里进行了两次复用,PDE起到了PTE,PT的作用。

      

  • 相关阅读:
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    8.4 确定两个日期之间的月份数或年数
    (Java实现) 洛谷 P1553 数字反转(升级版)
  • 原文地址:https://www.cnblogs.com/DreamoneOnly/p/11519418.html
Copyright © 2011-2022 走看看