博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
涨姿势系列之——内核环境下内存映射函数
阅读量:4984 次
发布时间:2019-06-12

本文共 2530 字,大约阅读时间需要 8 分钟。

同样是看别人代码时发现的,作者使用了MmGetPhysicalAddress和MmMapIoSpace这两个函数,之前从来没看过这两个函数还以为是作者自己写的呢。后来查了一下WDK原来是有文档的函数。作者是用这个函数把缓存模型I/O的地址取物理地址之后再映射出虚拟地址,虽然我没发现这么做有什么意义,因为对于缓冲I/O模式来说,IRP中给出的缓冲区地址已经是I/O管理器进行复制之后的结果了,不需要再进行什么映射,我也没搞懂作者是要干吗,不过可以学习一下这两个函数的使用。

PHYSICAL_ADDRESS  MmGetPhysicalAddress(    IN PVOID  BaseAddress    );

这个返回的就是直接的物理地址了。

typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;

可见 PHYSICAL_ADDRESS就是LARGE_INTEGER了。

 来看一下这个函数的源码吧,来自WRK。可见是通过获取PTE来取得物理地址的。宏的内容没有跟进去看了,但是想想就可以知道实现方法了,无非就是分页机制的原理。

1 PHYSICAL_ADDRESS 2 MmGetPhysicalAddress ( 3     __in PVOID BaseAddress 4     ) 5  6 { 7     PMMPTE PointerPte; 8     PHYSICAL_ADDRESS PhysicalAddress; 9 10     if (MI_IS_PHYSICAL_ADDRESS(BaseAddress)) 11     {12         PhysicalAddress.QuadPart = MI_CONVERT_PHYSICAL_TO_PFN (BaseAddress);13     }14     else 15     {16 17         PointerPte = MiGetPdeAddress (BaseAddress);18         if (PointerPte->u.Hard.Valid == 0) 19         {20             KdPrint(("MM:MmGetPhysicalAddressFailed base address was %p",21                       BaseAddress));22             ZERO_LARGE (PhysicalAddress);23             return PhysicalAddress;24         }25 26         if (MI_PDE_MAPS_LARGE_PAGE (PointerPte)) 27         {28             PhysicalAddress.QuadPart = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte) +29                                            MiGetPteOffset (BaseAddress);30         }31         else 32         {33             PointerPte = MiGetPteAddress (BaseAddress);34 35             if (PointerPte->u.Hard.Valid == 0) 36             {37                 KdPrint(("MM:MmGetPhysicalAddressFailed base address was %p",38                           BaseAddress));39                 ZERO_LARGE (PhysicalAddress);40                 return PhysicalAddress;41             }42             PhysicalAddress.QuadPart = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);43         }44     }45 46     PhysicalAddress.QuadPart = PhysicalAddress.QuadPart << PAGE_SHIFT;47     PhysicalAddress.LowPart += BYTE_OFFSET(BaseAddress);48 49     return PhysicalAddress;50 }

 

接下来看下这个函数

PVOID   MmMapIoSpace(    IN PHYSICAL_ADDRESS  PhysicalAddress,    IN SIZE_T  NumberOfBytes,    IN MEMORY_CACHING_TYPE  CacheType    );

同样是一个在WDK中有文档的函数,作用是把一个物理地址映射出来一个虚拟地址。PVOID返回值就是得到的虚拟地址。NumberOfBytes是映射的长度。所以这两个函数可以很好的配合使用啊,我的想法是在A进程中获取一个虚拟地址对应的物理地址,然后在B进程中把这个物理地址映射出来就可以使用啦,这样就突破每个进程的独立地址空间的局限啦。

顺带再说下,对于Windows内存管理不了解的童鞋可以不明白为啥获得物理地址后不直接使用,因为对于我们来说是不能直接使用物理地址的,我们平时接触到的都是经过分段+分页机制转化后的虚拟地址,而唯一能接触到物理地址的地方我想就是CR3寄存器中保存的PDE的基址了。

转载于:https://www.cnblogs.com/Ox9A82/p/5554492.html

你可能感兴趣的文章
js charAt()方法
查看>>
一些跨域问题
查看>>
配置RHEL&CentOS网络说明
查看>>
自动化测试工具 Test Studio入门教程
查看>>
【HTML学习手册】HTML介绍(一)
查看>>
Python之进程线程
查看>>
hbase shell-security(安全指令)
查看>>
C++整理
查看>>
Python中通过Image的open之后,去show结果打不开bmp图片,无法正常显示图片
查看>>
排序算法(一) —— 冒泡排序
查看>>
No.026:Remove Duplicates from Sorted Array
查看>>
SpringBoot项目的几种创建方式,启动、和访问
查看>>
设置gdb反汇编语法为intel(转载)
查看>>
窗外【1】
查看>>
解决"disabled". Expected Boolean, got Number with value 0
查看>>
Android 四大组件之Service
查看>>
【NLP新闻-2013.05.15】How Google is setting the new search standard with voice and knowledge graph...
查看>>
OC--init,initialize,initWithCoder:,initWithFrame:各方法的区别和加载顺序
查看>>
day10,day11—基本数据类型语法
查看>>
xml.dom.minidom
查看>>