我正在尝试使用虚拟地址从/ proc / [pid] / pagemap获取物理地址,我认为它工作正常,直到我尝试使用简单的测试程序。 这是我的代码,它使用虚拟地址获取物理地址:
#include "addresstranslation.h"
#include <stdio.h>
#define PAGEMAP_ENTRY 8
#define GET_BIT(X,Y) (X & ((uint64_t)1<<Y)) >> Y
#define GET_PFN(X) X & 0x7FFFFFFFFFFFFF
#define page_mapping_file "/proc/self/pagemap"
const int __endian_bit = 1;
#define is_bigendian() ( (*(char*)&__endian_bit) == 0 )
uintptr_t virtual_to_physical_address(uintptr_t virt_addr)
{
uintptr_t file_offset = 0;
uintptr_t read_val = 0;
uintptr_t page_number = 0;
int i = 0;
int c = 0;
int pid = 0;
int status = 0;
unsigned char c_buf[PAGEMAP_ENTRY];
FILE *f = fopen(page_mapping_file, "rb");
if(!f)
{
// if this happens run as root
printf("Error! Cannot open %s. Please, run as root.\n", page_mapping_file);
return 0;
}
file_offset = virt_addr / getpagesize() * PAGEMAP_ENTRY;
status = fseek(f, file_offset, SEEK_SET);
if(status)
{
printf("Error! Cannot seek in %s.\n", page_mapping_file);
perror("Failed to do fseek!");
fclose(f);
return 0;
}
for(i = 0; i < PAGEMAP_ENTRY; i++)
{
c = getc(f);
if(c == EOF)
{
fclose(f);
return 0;
}
if(is_bigendian())
{
c_buf[i] = c;
}
else
{
c_buf[PAGEMAP_ENTRY - i - 1] = c;
}
}
for(i=0; i < PAGEMAP_ENTRY; i++)
{
read_val = (read_val << 8) + c_buf[i];
}
/*
if(GET_BIT(read_val, 63))
{
page_number = GET_PFN(read_val);
printf("%d \n", page_number);
}
else
{
printf("Page not present\n");
}
if(GET_BIT(read_val, 62))
{
printf("Page swapped\n");
}
*/
fclose(f);
return read_val;
}
addresstranslation.h:
/*
* addresstranslation.h
*
* Translates virtual to physical address.
*/
#ifndef __ADDRESS_TRANSLATION_H
#define __ADDRESS_TRANSLATION_H
#include <inttypes.h>
#include <stdint.h>
uintptr_t virtual_to_physical_address(uintptr_t virt_addr);
#endif
这是我尝试的简单测试。
#include <stdlib.h>
#include <stdio.h>
#include "addresstranslation.h"
int main(int argc, char* argv[])
{
int *a1, *a2, *b1,*c1, *b2 = NULL;
int N = 4096;
uintptr_t ap1, ap2, bp1, bp2 = 0;
printf("Test virtual to physical address translation.\n");
a1 = (int*)malloc(sizeof(int) * N);
if (!a1)
{
printf("Error: cannot allocate memory for a\n");
return 1;
}
b1 = (int*)malloc(sizeof(int) * N);
if (!b1)
{
printf("Error: cannot allocate memory for b\n");
return 1;
}
ap1 = virtual_to_physical_address((uintptr_t)a1);
bp1 = virtual_to_physical_address((uintptr_t)b1);
printf("a1_virt= %p: a1_phys= %" PRIxPTR "\n", a1, ap1);
printf("b1_virt= %p b1_phys= %" PRIxPTR "\n", b1, bp1);
a2 = a1 + 1000;
b2 = b1 + 1;
ap2 = virtual_to_physical_address((uintptr_t)a2);
bp2 = virtual_to_physical_address((uintptr_t)b2);
printf("a2_virt= %p a2_phys= %" PRIxPTR "\n", a2, ap2);
printf("b2_virt= %p b2_phys= %" PRIxPTR "\n", b2, bp2);
printf("Done\n");
}
打印出类似这样的内容:
Test virtual to physical address translation.
a1_virt= 0x958d008: a1_phys= 4f8ce
b1_virt= 0x9591010 b1_phys= 4d40b
a2_virt= 0x958dfa8 a2_phys= 4f8ce
b2_virt= 0x9591014 b2_phys= 4d40b
Done
正如您所看到的,a1和a2具有不同的虚拟地址但具有相同的物理地址,我的问题是;我的虚拟物理地址转换是否有问题或是否与Linux内存管理有关,是否可以将一个物理地址映射到两个不同的虚拟地址?
答案 0 :(得分:1)
C语言区分大小写。
所以这个宏:
#DEFINE PAGE_MAPPING_FILE "/PROC/self/pagemap"
使用时不会调用:
FILE *f = fopen(page_mapping_file, "rb");
和#DEFINE
对C编译器没有任何意义。
正确的拼写是:#define
I.E.全部小写