您的位置:首页 > 其它

判断内存地址是否缺页

2015-12-27 00:00 323 查看
摘要: 判断某个地址的内存是否在物理内存

一个进程的内存是否加载到物理内存,系统是有记录的。记录文件就是/proc/$pid/pagemap

pagemap和内存地址的对应关系:

file_offset = virt_addr / PAGE_SIZE * PAGEMAP_ENTRY;

8字节的PAGEMAP_ENTRY用于记录这一页的内存映射信息:

* Bits 0-54 page frame number (PFN) if present

* 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

完整代码:

const int __endian_bit = 1 ;
#define PAGEMAP_ENTRY 8
#define is_bigendian () ( (*(char*)&__endian_bit) == 0 )
#define GET_BIT (X,Y) (X & ((uint64_t)1<<Y)) >> Y
#define GET_PFN (X) X & 0x7FFFFFFFFFFFFF
char page_path [0xff] = {0};
snprintf(page_path, sizeof(page_path ) - 1 , "/proc/%u/pagemap", getpid());
FILE* f = fopen(page_path, "rb");//open(page_path, O_RDONLY);
if(! f) return -1;
unsigned long file_offset = addr /  PAGE_SIZE * PAGEMAP_ENTRY;
int status = fseek(f, file_offset, SEEK_SET);
unsigned char c_buf [PAGEMAP_ENTRY];
for( int i = 0; i < PAGEMAP_ENTRY; i++)
{
int c = getc(f);
if( c == EOF) return -1;
if(is_bigendian()) c_buf[ i] = c;
else c_buf [PAGEMAP_ENTRY - i -1] = c;
}

unsigned long long read_val = 0;
for( int i = 0; i < PAGEMAP_ENTRY; i++)
{
read_val = ( read_val << 8) + c_buf[ i];
}

if(GET_BIT( read_val, 63))
printf("PFN: 0x%llx",(unsigned long long) GET_PFN(read_val));
else
printf( "page not present");

if(GET_BIT( read_val, 62))
printf( "Result: 0x%llx",  read_val );
fclose(f);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存缺页