2012-10-19 2 views
20

Ich möchte die Erinnerung an einen lebendigen Prozess erforschen, und wenn ich dies tue, darf der Prozess nicht gestört werden - also gdb an den Prozess anhängen (was würde es stoppen) ist keine Option. Deshalb möchte ich diese Informationen von/proc/kcore bekommen (wenn Sie eine andere Möglichkeit kennen, lassen Sie es mich bitte wissen). Also habe ich ein kleines Experiment gemacht. Ich habe eine Datei namens TEST mit nur "EXTRATESTEXTRA" erstellt. Dann öffnete ich es mit wenigerLesen des Prozessspeichers des Prozesses, ohne ihn zu unterbrechen (/ proc/kcore ist eine Option)

$ less TEST 

ich die PID dieses Prozesses mit

$ ps aux | grep TEST 
user 7785 0.0 0.0 17944 992 pts/8 S+ 16:15 0:00 less TEST 
user 7798 0.0 0.0 13584 904 pts/9 S+ 16:16 0:00 grep TEST 

bekam Und dann habe ich dieses Skript einen Dump aller Dateien zu erstellen:

#!/bin/bash 
grep rw-p /proc/$1/maps | sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' | while read start stop; do gdb --batch --pid $1 -ex "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; done 

(Ich fand es auf dieser Seite https://serverfault.com/questions/173999/dump-a-linux-processs-memory-to-file)

$ sudo ./dump_all_pid_memory.sh 7785 

Danach suchte ich nach „TRATESTEX“ in allen abgespeicherte Dateien:

$ grep -a -o -e '...TRATESTEX...' ./*.dump 
./7785-00624000-00628000.dump:HEXTRATESTEXTRA 
./7785-00b8f000-00bb0000.dump:EXTRATESTEXTRA 
./7785-00b8f000-00bb0000.dump:EXTRATESTEXTRA 

So stellte ich fest, dass es irgendwo ein Vorkommen dieser Zeichenfolge zwischen 0x00624000 und 0x00628000 sein muss. Daher konvertierte ich die Offsets in Dezimalzahlen und verwenden dd um den Speicher zu erhalten aus/proc/kcore:

$ sudo dd if="/proc/kcore" of="./y.txt" skip="0" count="1638400" bs=1 

Zu meiner Überraschung war die Datei y.txt voller Nullen (ich nicht die Zeichenfolge gefunden Ich habe darin gesucht).

Als Bonusüberraschung führte ich gleichzeitig einen ähnlichen Test mit einer anderen Testdatei durch und stellte fest, dass der andere Teststring, den ich verwendete (beide Prozesse mit weniger waren zur gleichen Zeit ausgeführt) bei gefunden werden sollte der gleiche Standort (das Dumping und das Greifen gaben den gleichen Offset). Also muss es etwas geben, was ich nicht klar verstehe.

  • Ist nicht das/proc/pid/maps den Offset des Speichers (dh zeigen soll: wenn es sagen würde, „XXX“ in 0x10 versetzt ist, könnte ein anderes Programm nicht die gleiche Uhr Offset verwenden werden Ich richtig? - das ist die Quelle meiner zweiten Überraschung)

  • Wie kann ich/proc/kmap lesen, um den Speicher zu bekommen, der zu einem Prozess gehört, den ich kenne?

EDIT - für zukünftigen stumblers (siehe Antwort unten zuerst)

Um die Antworten zusammenfassen und meinen eigenen Kommentar hinzu: -/proc/pid/maps zeigt die Teile des Speichers AS THE PROCESS SEES IT (unterschiedlich für jeden Prozess, Suche nach Speicherabbildung auf Linux), so dass verschiedene Prozesse scheinbar den gleichen Teil des Speichers verwenden (wie er aus ihrer Perspektive aussieht).Sie können die hier angegebenen Teile aus/proc/pid/mem als Super-User lesen (oder einen übergeordneten Prozess wie gdb tut es mit ptrace) - Speicher in /proc/kcore ist nicht das gleiche wie der Speicher aus der Perspektive des Prozesses in /proc/pid/mem - so Um nach dem Speicher des Prozesses in /proc/kcore zu suchen, müsste man herausfinden, wie der Speicher des Prozesses in Kernel-Speicher abgebildet wird (viele unordentliche Dinge und zeitraubend) Also um den Prozessspeicher zu bekommen, zuerst lesen, welche Regionen von /proc/pid/maps ist erlaubt Lesen/Schreiben von/nach und dann dump-copy die Regionen von /proc/pid/mem. Das Skript unten erstellt alle schreibbaren Bereiche (Quelle: https://unix.stackexchange.com/questions/6301/how-do-i-read-from-proc-pid-mem-under-linux). BEARBEITEN: Das überarbeitete funktionierende Python-Skript wird in eine eigene Antwort verschoben, so dass es von der Frage getrennt kommentiert werden kann.

+1

AFAIK, '/ proc/kcore' ist die Kernel Speicherplatz. Vielleicht passt '/ proc//mem' besser zu dem, was Sie erreichen möchten? – twalberg

+1

Warum fragst du und was genau willst du erreichen ??? Haben Sie den Fall in Betracht gezogen, in dem Überwachungs- und Überwachungsprozesse auf unterschiedlichen Prozessorkernen laufen, also gleichzeitig laufen (und ihren Adressraum "zufällig" anordnen)? –

+1

Der Python-Code wird nicht ausgeführt. Alles, was ich bekomme, ist ein Fehler: 'IndentionError: erwartet einen eingerückten Block'' in Zeile 5. :( – zrajm

Antwort

13

Für Prozess 1234 kann man seine Speicherabbildung erhalten, indem man sequentiell /proc/1234/maps (eine textuelle Pseudodatei) liest und den virtuellen Speicher durch zB liest read(2) -ing oder mmap(2) - geeignete Segmente der spärlichen Pseudo-Datei /proc/1234/mem.

Aber ich glaube, man kann nicht eine Art von Synchronisation vermeiden (vielleicht mit ptrace(2), wie gdb dem Fall ist), da der Prozess 1234 (und tut) jederzeit seinen Adressraum ändern (mit mmap & Zusammenhang syscalls).

Die Situation ist anders, wenn der überwachte Prozess 1234 nicht willkürlich ist, aber wenn Sie ihn verbessern könnten, um irgendwie mit dem Überwachungsprozess zu kommunizieren.

Ich bin nicht sicher zu verstehen, warum Sie das fragen. Und gdb ist in der Lage zu watch ein Ort, ohne den Prozess zu stoppen.

+0

Danke, am Ende habe ich beschlossen zu überwachen den Speicher über/proc/pid/maps und lies die dort angegebenen Bereiche aus/proc/pid/mem (Ich habe die Frage bearbeitet) – hmhmhmmm

0

Sie werden verwenden/proc // mem Prozess Speicher zu lesen, würde ich nicht lesen/proc/kcore oder einen der Kernel-Speicher-Funktionen empfehlen daher, (was zeitaufwendig)

15

Wenn Sie Root-Zugriff und sind auf einem Linux-System haben, können Sie den folgenden Linux-Skript verwenden (angepasst von Gilles' excellent unix.stackexchange.com answer und die Antwort ursprünglich in der Frage oben gegeben, aber einschließlich SyntaxErrors und sein pythonic nicht):

#!/usr/bin/env python 

import re 
import sys 

def print_memory_of_pid(pid, only_writable=True): 
    """ 
    Run as root, take an integer PID and return the contents of memory to STDOUT 
    """ 
    memory_permissions = 'rw' if only_writable else 'r-' 
    sys.stderr.write("PID = %d" % pid) 
    with open("/proc/%d/maps" % pid, 'r') as maps_file: 
     with open("/proc/%d/mem" % pid, 'r', 0) as mem_file: 
      for line in maps_file.readlines(): # for each mapped region 
       m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r][-w])', line) 
       if m.group(3) == memory_permissions: 
        sys.stderr.write("\nOK : \n" + line+"\n") 
        start = int(m.group(1), 16) 
        if start > 0xFFFFFFFFFFFF: 
         continue 
        end = int(m.group(2), 16) 
        sys.stderr.write("start = " + str(start) + "\n") 
        mem_file.seek(start) # seek to region start 
        chunk = mem_file.read(end - start) # read region contents 
        print chunk, # dump contents to standard output 
       else: 
        sys.stderr.write("\nPASS : \n" + line+"\n") 

if __name__ == '__main__': # Execute this code when run from the commandline. 
    try: 
     assert len(sys.argv) == 2, "Provide exactly 1 PID (process ID)" 
     pid = int(sys.argv[1]) 
     print_memory_of_pid(pid) 
    except (AssertionError, ValueError) as e: 
     print "Please provide 1 PID as a commandline argument." 
     print "You entered: %s" % ' '.join(sys.argv) 
     raise e 

wenn Sie dies als write_mem.py speichern, können Sie diese (mit python2.6 oder 2.7) laufen kann oder früh python2.5 (wenn Sie from __future__ import with_statement hinzufügen) als:

sudo python write_mem.py 1234 > pid1234_memory_dump 

pid1234 Speicher die dump Datei pid1234_memory_dump.

+0

Das only_writable-Flag funktioniert nicht, weil du immer noch beide Charaktere in deinem Regex-Match findest – BMDan

+0

Bitte, kann jemand das Skript bearbeiten? Es hat einen fehlenden Doppelpunkt um 12 (mit öffnen ("/ proc /% d/maps"% pid, 'r') als maps_file >> (hier) <<) –

+0

Script tat Der Trick - ich hatte ziemlich viel in einem GetSimple-Blog geschrieben, ohne zu merken, dass ich ausgeloggt war, also wenn ich "update" drücke, um meine Änderungen zu speichern, verlor es alles. Ich fand es aber alles im Speicher-Dump. Danke! – Scott

0

i erreicht dies, indem Sie den folgenden Befehl ausgeben

[root @ stage1 ~] # "Speichernutzung für PID [MySql]:" echo; für mem in {Privat, Rss, Shared, Swap, Pss}; mach grep $ mem/proc/ps aux |grep mysql |awk '{print $2}'|head -n 1/smaps | awk -v mem_type = "$ mem" '{i = i + $ 2} END {print mem_type, "Speichernutzung:" i}';

getan

Ergebnisausgabe

Speichernutzung für PID [MySql] :

privater Speicherverbrauch: 204

Rss Speichernutzung: 1264

Shared-Memory-Nutzung: 1060

Swap-Speicher uns Alter: 0

Pss Speicherverbrauch: 423

+0

Die Frage betrifft nicht die Speichernutzung – tuxayo

Verwandte Themen