如何在Linux中从用户空间中找到变量的物理地址?

San*_*dip 14 c linux

我想找到在用户空间进程中定义的变量的物理地址?有没有办法使用root权限?

ing*_*net 18

正如之前部分回答的那样,普通程序不需要担心物理地址,因为它们在虚拟地址空间中运行并具有所有便利性.此外,并非每个虚拟地址都具有物理地址,可以属于映射文件或交换页面.但是,有时看到这种映射可能会很有趣,即使在用户区也是如此.

为此,Linux内核通过一组文件公开其到userland的映射/proc.文档可以在这里找到.简短的摘要:

  1. /proc/$pid/maps 提供虚拟地址映射列表以及附加信息,例如映射文件的相应文件.
  2. /proc/$pid/pagemap 提供有关每个映射页面的更多信息,包括物理地址(如果存在).

该网站提供了一个C程序,它使用此接口转储所有正在运行的进程的映射,并解释它的作用.


aus*_*len 16

#include "stdio.h"
#include "unistd.h"
#include "inttypes.h"

uintptr_t vtop(uintptr_t vaddr) {
    FILE *pagemap;
    intptr_t paddr = 0;
    int offset = (vaddr / sysconf(_SC_PAGESIZE)) * sizeof(uint64_t);
    uint64_t e;

    // https://www.kernel.org/doc/Documentation/vm/pagemap.txt
    if ((pagemap = fopen("/proc/self/pagemap", "r"))) {
        if (lseek(fileno(pagemap), offset, SEEK_SET) == offset) {
            if (fread(&e, sizeof(uint64_t), 1, pagemap)) {
                if (e & (1ULL << 63)) { // page present ?
                    paddr = e & ((1ULL << 54) - 1); // pfn mask
                    paddr = paddr * sysconf(_SC_PAGESIZE);
                    // add offset within page
                    paddr = paddr | (vaddr & (sysconf(_SC_PAGESIZE) - 1));
                }   
            }   
        }   
        fclose(pagemap);
    }   

    return paddr;
}   
Run Code Online (Sandbox Code Playgroud)


Pin*_*ain -4

首先,你为什么要这样做?现代VM系统的目的是让应用程序程序员摆脱物理内存布局的复杂性。为他们每个人提供自己的统一地址空间,让他们的生活更轻松。

如果您确实想这样做,那么您几乎肯定需要使用内核模块。以正常方式获取变量的虚拟地址,使用它来索引进程页表并读取找到的值(帧的物理地址)。然后加上页偏移即可得到完整的物理地址。请注意,启用寻呼时您将无法使用此地址。

(如果幸运的话,您可能能够从 /proc 文件系统获取 VM 区域的帧地址,因此不需要编写内核模块。)

  • *“你为什么要这样做?”*不是答案 (21认同)
  • ...除非您将页面锁定到内存中,否则该物理地址可能随时更改。 (7认同)
  • 您不需要编写内核模块:正如其他示例所解释的那样,这已经通过“/proc/$pid/pagemap”公开了。 (4认同)