1.Linux文件目录中的/proc记录着当前进程的信息,称其为虚拟文件系统。在/proc下有一个链接目录名为self,这意味着哪一个进程打开了它,self中存储的信息就是所链接进程的。self中有一个名为pagemap的文件,专门用来记录所链接进程的物理页号信息。这样通过/proc/pid/pagemap文件,允许一个用户态的进程查看到每个虚拟页映射到的物理页
2./proc/pid/pagemap中的每一项都包含了一个64位(8字节)的值,这个值内容如下所示。每一项的映射方式不同于真正的虚拟地址映射,其文件中遵循独立的对应关系,即虚拟地址相对于0x0经过的页面数是对应项在文件中的偏移量/proc/pid/pagemap. This file lets a userspace process find out which
physical frame each virtual page is mapped to. It contains one 64-bit
value for each virtual page, containing the following data (from
fs/proc/task_mmu.c, above pagemap_read):
* Bits 0-54 page frame number (PFN) if present//present为1时,bit0-54表示物理页号
* Bits 0-4 swap type if swapped
* Bits 5-54 swap offset if swapped
* Bit 55 pte is soft-dirty (see Documentation/vm/soft-dirty.txt)
* Bit 56 page exclusively mapped (since 4.2)
* Bits 57-60 zero
* Bit 61 page is file-page or shared-anon (since 3.5)
* Bit 62 page swapped
* Bit 63 page present//如果为1,表示当前物理页在内存中;为0,表示当前物理页不在内存中在计算物理地址时,只需要找到虚拟地址的对应项,再通过对应项中的bit63判断此物理页是否在内存中,若在内存中则对应项中的物理页号加上偏移地址,就能得到物理地址
通过程序获取物理地址#include
#include
#include
#include
#include
// /proc虚拟文件系统
// /self链接目录名,这意味着哪一个进程打开了它,self中存储的信息就是所链接进程的
// self下面有个pagemap文件,专门用来记录所链接进程的物理页号信息
int phy_(unsigned long vir_addr,uint64_t *phy_addr)
{
//计算虚拟地址相对于0X0偏移的页面数
unsigned long int v_pageIndex = vir_addr/getpagesize();
//计算物理页面在/proc/self/pagemap中的偏移量
unsigned long int v_offset = v_pageIndex * sizeof(uint64_t);
//计算物理地址在物理页面中的偏移量
unsigned long int move = vir_addr % getpagesize();
int fd = open("/proc/self/pagemap",O_RDONLY);
uint64_t item;//还没取低55位的物理页号
uint64_t phy_page;//取了低55位的物理页号
lseek(fd,v_offset,SEEK_SET);
uint64_t x = read(fd,&item,sizeof(uint64_t));
printf("%lld\n",x);
phy_page = (((uint64_t)1<<55)-1) & item ;
*phy_addr = phy_page*getpagesize()+move;
return 0;
}
int b = 10;
int main()
{
int * a = (int *)malloc(sizeof(int));
uint64_t phy_addr;
//phy_((unsigned long)&a,phy_addr);
pid_t pid = fork();
if(pid == 0)
{
;
}
phy_((unsigned long)a,&phy_addr);
printf("a cal = %x\n,a phy = %x\n",a,phy_addr);
return 0;
}