Das folgende Quick-and-Dirty-Python-Skript gibt den Speicher eines Prozesses auf stdout aus. Dies hat den Nebeneffekt, dass jede ausgelagerte Seite oder zugeordnete Datei geladen wird. Nennen Sie es als cat_proc_mem 123 456 789
wobei die Argumente Prozess-IDs sind.
Dieses Skript ist vollständig spezifisch für Linux. Es kann an andere Systeme mit einem ähnlichen /proc
angepasst werden Struktur (Solaris?), aber vergiss es z.B. *BSD. Sogar unter Linux müssen Sie möglicherweise die Definition von c_pid_t
ändern und die Werte von PTRACE_ATTACH
und PTRACE_DETACH
. Dies ist ein Proof-of-Principle-Skript, das nicht als Beispiel für gute Programmierpraktiken gedacht ist. Verwendung auf eigene Gefahr.
Linux stellt den Speicher eines Prozesses als /proc/$pid/mem
zur Verfügung . Nur bestimmte Adressbereiche sind lesbar. Diese Bereiche können gefunden werden, indem die Speicherzuordnungsinformationen aus der Textdatei /proc/$pid/maps
gelesen werden . Die Pseudodatei /proc/$pid/mem
kann nicht von allen Prozessen gelesen werden, die die Berechtigung zum Lesen haben:Der Leseprozess muss ptrace(PTRACE_ATTACH, $pid)
aufgerufen haben .
#!/usr/bin/env python
import ctypes, re, sys
## Partial interface to ptrace(2), only for PTRACE_ATTACH and PTRACE_DETACH.
c_ptrace = ctypes.CDLL("libc.so.6").ptrace
c_pid_t = ctypes.c_int32 # This assumes pid_t is int32_t
c_ptrace.argtypes = [ctypes.c_int, c_pid_t, ctypes.c_void_p, ctypes.c_void_p]
def ptrace(attach, pid):
op = ctypes.c_int(16 if attach else 17) #PTRACE_ATTACH or PTRACE_DETACH
c_pid = c_pid_t(pid)
null = ctypes.c_void_p()
err = c_ptrace(op, c_pid, null, null)
if err != 0: raise SysError, 'ptrace', err
## Parse a line in /proc/$pid/maps. Return the boundaries of the chunk
## the read permission character.
def maps_line_range(line):
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
return [int(m.group(1), 16), int(m.group(2), 16), m.group(3)]
## Dump the readable chunks of memory mapped by a process
def cat_proc_mem(pid):
## Apparently we need to ptrace(PTRACE_ATTACH, $pid) to read /proc/$pid/mem
ptrace(True, int(pid))
## Read the memory maps to see what address ranges are readable
maps_file = open("/proc/" + pid + "/maps", 'r')
ranges = map(maps_line_range, maps_file.readlines())
maps_file.close()
## Read the readable mapped ranges
mem_file = open("/proc/" + pid + "/mem", 'r', 0)
for r in ranges:
if r[2] == 'r':
mem_file.seek(r[0])
chunk = mem_file.read(r[1] - r[0])
print chunk,
mem_file.close()
## Cleanup
ptrace(False, int(pid))
if __name__ == "__main__":
for pid in sys.argv[1:]:
cat_proc_mem(pid)
Siehe auch weitere Informationen zu /proc/$pid/mem
.
unswap () {
cat_proc_mem "[email protected]" >/dev/null
}
Wenn Sie wirklich wieder genug RAM zur Verfügung haben, können Sie diese Sequenz (als root) verwenden:
$ swapoff -a
$ swapon -a
(um das explizite Einlagern aller Ihrer Anwendungen zu erzwingen)
(vorausgesetzt, Sie verwenden Linux)
Nur der Vollständigkeit halber kann GDB das Prozessabbild ausgeben. Ich habe nicht überprüft, ob es ausgelagert wird, aber es muss --- es gibt keine andere Möglichkeit, den gesamten Prozessspeicher zu lesen:
gdb -p $mypid
gefolgt von
(gdb) gcore /tmp/myprocess-core
Saved corefile /tmp/myprocess-core