El siguiente script de Python rápido y sucio volca la memoria de un proceso en stdout. Esto tiene el efecto secundario de cargar cualquier página intercambiada o archivo asignado. Llámelo como cat_proc_mem 123 456 789
donde los argumentos son ID de proceso.
Este script es completamente específico para Linux. Puede ser adaptable a otros sistemas con una /proc
estructura similar (Solaris?), Pero olvídate de ejecutarlo, por ejemplo, * BSD. Incluso en Linux, es posible que deba cambiar la definición c_pid_t
y los valores de PTRACE_ATTACH
y PTRACE_DETACH
. Este es un script de prueba de principio, no como un ejemplo de buenas prácticas de programación. Úselo bajo su propio riesgo.
Linux hace que la memoria de un proceso esté disponible como /proc/$pid/mem
. Solo ciertos rangos de direcciones son legibles. Estos rangos se pueden encontrar leyendo la información de asignación de memoria del archivo de texto /proc/$pid/maps
. El pseudoarchivo /proc/$pid/mem
no puede ser leído por todos los procesos que tienen permiso para leerlo: el proceso del lector debe haber llamado ptrace(PTRACE_ATTACH, $pid)
.
#!/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)
Ver también más información sobre/proc/$pid/mem
.
unswap () {
cat_proc_mem "$@" >/dev/null
}
swapon
/swapoff
(como sugiere la respuesta actualmente aceptada), es posible que desee cancelar el intercambio de su administrador de pantalla y todos sus elementos secundarios al volcar sus memorias de proceso (lo que fuerza el cambio). Consulte también "¿Cómo forzar el intercambio de un proceso zsh intercambiado?" En stackoverflow.