2013-06-10 6 views
8

Ich versuche zu entschlüsseln, wie/proc/pid/pagemap zu verwenden, um die physische Adresse eines bestimmten Satzes von Seiten zu erhalten. Angenommen, aus/proc/pid/maps erhalte ich die virtuelle Adresse afa2d000-afa42000, die dem Heap entspricht. Meine Frage ist, wie verwende ich diese Informationen, um die pagmap-Datei zu durchlaufen und finde die physischen Seitenrahmen, die der Adresse afa2d000-afa42000 entsprechen.Wie dekodieren/proc/pid/pagemap Einträge in Linux?

Der Eintrag/proc/pid/pagemap ist im Binärformat. Gibt es Tools, um die Analyse dieser Datei zu erleichtern?

Antwort

2

Versuchen Sie, diese http://www.eqware.net/Articles/CapturingProcessMemoryUsageUnderLinux/ Es kann die pagemap für Sie, zum Beispiel analysieren, wenn die virtuelle Adresse Sie interessiert sind, in der Halde ist die 0x055468 ist: = 0004c000-0005a000 rw-p 00000000 00:00 0 [ Haufen] : 86000000000FD6D6 : 0600000000000000
: 0600000000000000
: 86000000000FE921
: 86000000000FE922
: 0600000000000000
: 86000000000FD5AD
: 86000000000FD6D4
: 86000000000FD5F8
: 86000000000FD5FA => 9.

die Seitengröße als 4 KB Nehmen wir an, und (0x055468 - 0x4c000) mod 4K = 9, So ist die Seitenrahmennummer Ihrer Seite ist die neunte Seite Rahmen ==>: 86000000000FD5FA So ist die physische PFN 0xFD5FA000 (nehmen Sie die letzten 55 Bits und mal Seitengröße) plus Offset: (0x055468 - 0x4c000 - 9 * 4K) = 0x468 ==> die physische Adr ist 0xFD5FA000 + 0x468 = 0xFD5FA468

+0

Haben Sie page-analyse.cpp erfolgreich kompiliert, abgesehen von der fehlenden #include bekomme ich diesen Compilerfehler: 'page-analyze.cpp: In Funktion 'void make_kurzname (char *, const char *)': page-analyze.cpp: 135: 35: Fehler: Zuweisung des schreibgeschützten Speicherortes '* strchr (b, 93)' make: ** * [page-analyze] Fehler 1' – JohnnyFromBF

+0

Es tut mir leid, Link beiseite, die Antwort sollte selbst Sinn machen, aber ist IMO sehr schlecht geschrieben. Benötigte Formatierung, die Quelle der Daten ist nicht klar/demonstriert ... auch dass "mod" "div" sein muss – nhed

1

Linux Kernel-Dokumentation

Linux-Kernel doc beschreibt das Format: https://github.com/torvalds/linux/blob/v4.9/Documentation/vm/pagemap.txt

* 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 

C Parserfunktion

GitHub upstream.

#define _XOPEN_SOURCE 700 
#include <fcntl.h> /* open */ 
#include <stdint.h> /* uint64_t */ 
#include <stdlib.h> /* size_t */ 
#include <unistd.h> /* pread, sysconf */ 

typedef struct { 
    uint64_t pfn : 54; 
    unsigned int soft_dirty : 1; 
    unsigned int file_page : 1; 
    unsigned int swapped : 1; 
    unsigned int present : 1; 
} PagemapEntry; 

/* Parse the pagemap entry for the given virtual address. 
* 
* @param[out] entry  the parsed entry 
* @param[in] pagemap_fd file descriptor to an open /proc/pid/pagemap file 
* @param[in] vaddr  virtual address to get entry for 
* @return 0 for success, 1 for failure 
*/ 
int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr) 
{ 
    size_t nread; 
    ssize_t ret; 
    uint64_t data; 

    nread = 0; 
    while (nread < sizeof(data)) { 
     ret = pread(pagemap_fd, &data, sizeof(data), 
       (vaddr/sysconf(_SC_PAGE_SIZE)) * sizeof(data) + nread); 
     nread += ret; 
     if (ret <= 0) { 
      return 1; 
     } 
    } 
    entry->pfn = data & (((uint64_t)1 << 54) - 1); 
    entry->soft_dirty = (data >> 54) & 1; 
    entry->file_page = (data >> 61) & 1; 
    entry->swapped = (data >> 62) & 1; 
    entry->present = (data >> 63) & 1; 
    return 0; 
} 

Beispiel runnable Programme es mit:

0

Falls Leute wollen Um dies von Rust zu tun, habe ich eine Rust-Implementierung hinzugefügt, so dass Sie leicht navigieren können und /proc/$pid/pagemap: https://crates.io/crates/vm-info