Le script python rapide et sale suivant vide la mémoire d'un processus vers stdout. Cela a pour effet secondaire de charger une page ou un fichier mappé. Appelez-le comme cat_proc_mem 123 456 789
où les arguments sont des ID de processus.
Ce script est complètement spécifique à Linux. Il peut être adaptable à d'autres systèmes avec une /proc
structure similaire (Solaris?), Mais oubliez de l'exécuter par exemple sur * BSD. Même sous Linux, vous devrez peut-être modifier la définition c_pid_t
et les valeurs de PTRACE_ATTACH
et PTRACE_DETACH
. Il s'agit d'un script de preuve de principe, non pas comme un exemple de bonnes pratiques de programmation. À utiliser à vos risques et périls.
Linux rend la mémoire d'un processus disponible en /proc/$pid/mem
. Seules certaines plages d'adresses sont lisibles. Ces plages peuvent être trouvées en lisant les informations de mappage de mémoire dans le fichier texte /proc/$pid/maps
. Le pseudo-fichier /proc/$pid/mem
ne peut pas être lu par tous les processus autorisés à le lire: le processus lecteur doit avoir appelé 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)
Voir aussi plus d'informations sur/proc/$pid/mem
.
unswap () {
cat_proc_mem "$@" >/dev/null
}
swapon
/swapoff
(comme le suggère la réponse actuellement acceptée), vous souhaiterez peut-être annuler l'échange de votre gestionnaire d'affichage et de tous ses enfants en vidant leurs mémoires de processus (ce qui force l'annulation de l'échange). Voir aussi «Comment forcer un processus zsh échangé à swap dedans?» Sur stackoverflow.