Seit der Version 3.2 des Kernels. Sie können den Systemaufruf process_vm_readv verwenden, um den Prozessspeicher ohne Unterbrechung zu lesen.
ssize_t process_vm_readv(pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags);
Diese Systemaufrufe übertragen Daten zwischen dem Adressraum des aufrufenden Prozesses ("dem lokalen Prozess") und dem durch pid identifizierten Prozess ("dem entfernten Prozess"). Die Daten bewegen sich direkt zwischen den Adressräumen der beiden Prozesse, ohne den Kernelspace zu durchlaufen.
Für Prozess 1234 können Sie seine Speicherabbildung erhalten, indem Sie nacheinander /proc/1234/maps
lesen (eine textuelle Pseudodatei) und den virtuellen Speicher lesen, z. read(2)-ing oder mmap(2)-ing entsprechende Segmente von /proc/1234/mem
Sparse-Pseudo-Datei.
Ich glaube jedoch, dass Sie eine Art Synchronisation nicht vermeiden können (vielleicht mit ptrace(2), als gdb
). tut), da der Prozess 1234 seinen Adressraum jederzeit ändern kann (und tut) (mit mmap
&verwandte Systemaufrufe).
Die Situation ist anders, wenn der überwachte Prozess 1234 nicht willkürlich ist, sondern wenn Sie ihn verbessern könnten, um irgendwie mit dem überwachenden Prozess zu kommunizieren.
Ich bin mir nicht sicher, zu verstehen, warum Sie das fragen. Und gdb
kann watch
bestimmten Ort, ohne den Prozess zu stoppen.
Wenn Sie Root-Zugriff haben und sich auf einem Linux-System befinden, können Sie das folgende Linux-Skript verwenden (angepasst an Gilles hervorragende unix.stackexchange.com-Antwort und die Antwort, die ursprünglich in der obigen Frage gegeben wurde, aber SyntaxErrors enthält und nicht pythonisch ist):
#!/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 dies (mit python2.6 oder 2.7) oder früh in python2.5 (wenn Sie from __future__ import with_statement
hinzufügen) ausführen ) als:
sudo python write_mem.py 1234 > pid1234_memory_dump
um den pid1234-Speicher in die Datei pid1234_memory_dump.
zu kopieren