一個進程的內存是否加載到物理內存,系統是有記錄的。記錄文件就是/proc/$pid/pagemap
app
pagemap和內存地址的對應關係:
ui
file_offset = virt_addr / PAGE_SIZE * PAGEMAP_ENTRY;spa
8字節的PAGEMAP_ENTRY用於記錄這一頁的內存映射信息:code
* Bits 0-54 page frame number (PFN) if present進程
* Bits 0-4 swap type if swapped內存
* Bits 5-54 swap offset if swappedget
* Bit 55 pte is soft-dirty (see Documentation/vm/soft-dirty.txt)it
* Bit 56 page exclusively mapped (since 4.2)io
* Bits 57-60 zeroclass
* 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);