当前位置:  开发笔记 > 编程语言 > 正文

如何将虚拟内存地址转换为物理地址?

如何解决《如何将虚拟内存地址转换为物理地址?》经验,为你挑选了4个好方法。

在我的C++程序中(在Windows上),我正在分配一块内存,并确保它在物理内存中保持锁定(未连接和连续)(即使用VirtualAllocEx(),MapUserPhysicalPages()等).

在我的过程中,我可以获得该块的VIRTUAL内存地址, 但我需要找出它的PHYSICAL内存地址,以便将其传递给某个外部设备.


1.在USER模式下,有什么方法可以将虚拟地址转换为程序中的物理地址吗?

2.如果没有,我只能在KERNEL模式下找到这个虚拟到物理映射.我想这意味着我必须写一个驱动程序才能做到这一点......?你知道我可以使用的任何现成的驱动程序/ DLL/API,我的应用程序(程序)将与之交互以进行翻译吗?

3.如果我必须自己编写驱动程序,我该如何进行翻译?我使用哪些功能?是mmGetPhysicalAddress()吗?我该如何使用它?

4.此外,如果我理解正确,mmGetPhysicalAddress()将返回调用进程上下文中的虚拟基址的物理地址.但是如果调用进程是驱动程序,并且我正在使用我的应用程序来调用该函数的驱动程序,那么我正在改变上下文,当调用mmGetPhysicalAddress例程时,我不再处于应用程序的上下文中...所以如何翻译应用程序(用户模式)内存空间中的虚拟地址,而不是驱动程序?

任何答案,提示和代码摘录将不胜感激!

谢谢



1> bk1e..:

在我的C++程序中(在Windows上),我正在分配一块内存,并确保它在物理内存中保持锁定(未连接和连续)(即使用VirtualAllocEx(),MapUserPhysicalPages()等).

不,你无法确保它保持锁定状态.如果您的流程崩溃或提前退出怎么办?如果用户杀了它怎么办?该内存将被重用于其他内容,如果您的设备仍在执行DMA,最终将导致数据丢失/损坏或错误检查(BSOD).

此外,它MapUserPhysicalPages是Windows AWE(Address Windowing Extensions)的一部分,用于在32位版本的Windows Server上处理超过4 GB的RAM.我不认为它是用于破解用户模式DMA.

1.在USER模式下,有什么方法可以将虚拟地址转换为程序中的物理地址吗?

有些驱动程序允许您执行此操作,但您无法在Windows上从用户模式编程DMA,并且仍然具有稳定且安全的系统.让作为受限用户帐户运行的进程读/写物理内存允许该进程拥有系统.如果这是一次性系统或原型,这可能是可以接受的,但如果您希望其他人(特别是付费客户)使用您的软件和您的设备,您应该编写驱动程序.

2.如果没有,我只能在KERNEL模式下找到这个虚拟到物理映射.我想这意味着我必须写一个驱动程序才能做到这一点......?

这是解决此问题的推荐方法.

你知道我可以使用的任何现成的驱动程序/ DLL/API,我的应用程序(程序)将与之交互以进行翻译吗?

您可以使用MDL(内存描述符列表)锁定任意内存,包括用户模式进程拥有的内存缓冲区,并将其虚拟地址转换为物理地址.您还可以让Windows DeviceIoControl通过使用METHOD_IN_DIRECT或临时为传递给调用的缓冲区创建MDL METHOD_OUT_DIRECT.

请注意,虚拟地址空间中的连续页面在物理地址空间中几乎不会连续.希望您的设备能够处理这个问题.

3.如果我必须自己编写驱动程序,我该如何进行翻译?我使用哪些功能?是mmGetPhysicalAddress()吗?我该如何使用它?

编写驱动程序要比调用一些API要多得多.如果您要编写驱动程序,我建议您从MSDN和OSR中尽可能多地阅读相关材料.另外,请查看Windows驱动程序工具包中的示例.

4.另外,如果我理解正确,mmGetPhysicalAddress()将返回调用进程上下文中的虚拟基址的物理地址.但是如果调用进程是驱动程序,并且我正在使用我的应用程序来调用该函数的驱动程序,那么我正在改变上下文,当调用mmGetPhysicalAddress例程时,我不再处于应用程序的上下文中...所以如何翻译应用程序(用户模式)内存空间中的虚拟地址,而不是驱动程序?

驱动程序不是进程.驱动程序可以在任何进程的上下文中运行,也可以在各种提升的上下文(中断处理程序和DPC)中运行.



2> Christopher..:

1)没有

2)是的,你必须写一个驱动程序.Best可以是虚拟驱动程序,也可以更改特殊外部设备的驱动程序.

3)这在这里变得非常混乱.MmGetPhysicalAddress应该是您正在寻找的方法,但我真的不知道物理地址如何映射到bank/chip/etc. 在物理记忆上.

4)你不能使用分页内存,因为它被重新定位.您可以MmProbeAndLockPages在MDL上锁定分页内存,您可以在从用户模式调用上下文传入的内存上构建.但最好分配非分页内存并将其交给用户模式应用程序.

PVOID p = ExAllocatePoolWithTag( NonPagedPool, POOL_TAG );
PHYSICAL_ADDRESS realAddr = MmGetPhysicalAddress( p );

// use realAddr



3> 小智..:

您的应用程序中有一个虚拟缓冲区.正如您所指出的那样,该范围的虚拟内存仅在您的应用程序的上下文中可用,并且其中一些可能随时被分页.因此,为了从设备访问内存(也就是说,执行DMA),您需要将其锁定并获取可以传递给设备的描述.

通过使用METHOD_IN_DIRECT或METHOD_OUT_DIRECT将IOCTL(通过DeviceControl函数)发送到驱动程序,可以获得称为MDL或内存描述符列表的缓冲区的描述.有关定义IOCTL的讨论,请参见以下页面.

http://msdn.microsoft.com/en-us/library/ms795909.aspx

现在您已在设备的驱动程序中描述了缓冲区,您可以将其锁定,以便缓冲区在设备可能对其执行的整个时间段内保留在内存中.在MSDN上查找MmProbeAndLockPages.

您的设备可能会也可能无法读取或写入缓冲区中的所有内存.该设备可能只支持32位DMA,机器可能有超过4GB的RAM.或者您可能正在处理具有IOMMU,GART或其他地址转换技术的计算机.为了适应这种情况,请使用各种DMA API来获取一组适合您的设备使用的逻辑地址.在许多情况下,这些逻辑地址将等同于您提出的问题的物理地址,但并非总是如此.

您使用哪种DMA API取决于您的设备是否可以处理分散/收集列表等.您的驱动程序在其设置代码中将调用IoGetDmaAdapter并使用它返回的一些函数.

通常,您会对GetScatterGatherList和PutScatterGatherList感兴趣.您提供了一个函数(ExecutionRoutine),它实际上对您的硬件进行编程以进行传输.

涉及很多细节.祝好运.



4> RandomNickNa..:

您无法从用户空间访问页表,它们将映射到内核中.

如果您在内核中,只需检查CR3的值以找到基页表地址,然后开始解析.

这个博客系列有一个如何做到这一点的精彩解释.您不需要任何OS工具/ API来解析虚拟< - >物理地址.

虚拟地址:f9a10054

1: kd> .formats 0xf9a10054
Binary:  11111001 10100001 00000000 01010100

Page Directory Pointer Index(PDPI)       11                        Index into

第1个表(页面目录指针表)页目录索引(PDI)
111001 101索引到第2个表(页面目录表)页表索引(PTI)
00001 0000索引到第3个表(页表)字节索引
0000 01010100 0x054,偏移到物理内存页面

在他的例子中,他们使用windbg,!dq是物理内存读取.

在此输入图像描述

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有