HYPERSPACE
Windows中,不管是应用程序还是内核程序,都不能直接访问物理内存,所有非IO指令都只能访问虚拟内存地址,如Mov eax, DWORD PTR[虚拟地址]形式,但是,有时候,我们明明已经知道了某个东西固定在物理内存条某处,假如系统时间的值永远固定存放在物理内存条的物理地址0x80000000处,我们已经知道了物理地址,如何访问获得系统时间值呢?这是个问题!Windows为了解决这样的直接访问物理内存操作提供了手段!其中之一便是:“为物理页面建立临时映射”,也即可以将某个物理页面映射到系统地址空间中的那段专用于临时页面映射的保留区域。
系统地址空间中专用于临时映射的那段保留区的起始虚拟地址为:#define HYPERSPACE 0xC0400000
保留区的大小为:1024个虚拟页面,也即1024*4KB=4MB大小
函数MmCreateHyperspaceMapping用来将指定物理页面 临时 映射到保留区中的某个虚拟页面,返回得到的虚拟页面地址
Void* MmCreateHyperspaceMapping(pfn) { PTE* Pte=临时映射保留区的映射描述符们所在的二级页表;//也即第一个临时页面的映射描述符 Pte+=pfn%1024;//从这个虚拟页面的映射描述符开始,向后搜索第一个尚未映射的虚拟页面 For(i=pfn%1024; i<1024; i++,Pte++)//先遍历后面的那些PTE { If(*pte == 空白) { *pte.pfn=pfn; Break; } } If(i==1024)//如果后面部分未找到一个空闲PTE,又从前面部分开始查找 { PTE* Pte=临时映射保留区的映射描述符们所在的二级页表;//回到开头 For(i=0; i<pfn%1024;i++,Pte++) { If(*pte == 空白) { *pte.pfn=pfn; Break; } }//end for }//end if(i==1024) //上面是一个简单的闭式hash表的查找过程,找到一个尚未映射的临时保留虚拟页面后,就返回 Return HYPERSPACE + i*4kb; }
既然叫临时映射,那用完后,就得撤销映射:MmDeleteHyperspaceMapping(pfn);//这个函数就是用来删除以前建立的临时映射