代码之家  ›  专栏  ›  技术社区  ›  Ross Rogers

在使用C++和GCC的Linux中,有可能将虚拟地址转换成物理地址吗?

  •  2
  • Ross Rogers  · 技术社区  · 14 年前

    在Linux、C++和GCC下,我能得到一个给定的虚拟地址的物理地址吗?我知道我不能把物理地址当作物理地址来操作。

    4 回复  |  直到 13 年前
        1
  •  6
  •   Jonathan Grynspan    14 年前

    不。不能保证虚拟地址是基于物理地址的(例如,它可能是一个在RAM中没有表示的映射文件)。而且,操作系统可以随时在物理内存中自由移动虚拟地址,因此不能保证物理地址将保持正确或有效。

    为什么你认为你需要一个物理地址?你想完成什么?

        2
  •  3
  •   pm100    14 年前

    我相信您可以编写一个Linux内核模块,告诉您地址空间是如何映射的。那会很有趣的

    或查看/proc/pid/maps

    我在看 http://www.amazon.com/Linux-Kernel-Development-Robert-Love/dp/0672325128

        3
  •  1
  •   nategoose    14 年前

    如果代码不在内核中运行,就没有很好的方法可以做到这一点,但是如果您的程序在根目录下运行,并且您能够读取 /proc/kcore (也许) /proc/kallsyms )通过大量的工作,我们能够为您的流程找到页表信息,并在其中查找地址。

    问题是,当你这样做的时候,你的程序不会保持原样。即使包含地址的页面从未被调出过,它也可以被移动(在x86上,有些页面不能用于DMA,因此可以移动一个页面来设置IO操作,而且我确信还有其他原因可以移动一个页面而不被换出)。

    此外,当您阅读页表时,它们会发生变化。您不能像在内核空间中那样将它们从应用程序空间锁定,所以我不确定您是否可以对这种结构进行良好的快照。

    如果您真的想看到页面地址随着程序的变化而变化,那么最好的办法就是实现一个内核模块,它允许您查询页面地址,或者在每次调用特殊设备文件时读取整个页面映射。我不认为这太难,因为当前进程的进程控制块在调用驱动程序的读取函数时可用。如果您希望能够检查其他进程的映射,这将变得更加棘手。

        4
  •  1
  •   Tommy    13 年前

    我也遇到过类似的问题,昨天把它贴了出来。大多数情况下,每个答案似乎都说你“不能”这样做,但根据下面的链接,这是非常可行的。结果表明,您可以通过两种方式来实现这一点:创建一个独立的守护进程工具,并监视/proc/$pid/maps和/proc$pid/page maps(这是一个包含物理页地址的二进制文件)。 紧随其后 link 您可以查看他们的程序,并希望根据您自己的目的对其进行调优。或者您可以简单地停止程序并调用这个工具来读取/proc中的当前信息。希望这有帮助。

    编辑 我必须为我自己的目的调整工具,这 header 信息应该能帮到你。