GNU/Linux >> Tutoriels Linux >  >> Linux

Lire la mémoire des processus vivants sans l'interrompre

Depuis la version 3.2 du noyau. Vous pouvez utiliser l'appel système process_vm_readv pour lire la mémoire du processus sans interruption.

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);

Ces appels système transfèrent des données entre l'espace d'adressage du processus appelant ("le processus local") et le processus identifié par pid ("le processus distant"). Les données se déplacent directement entre les espaces d'adressage des deux processus, sans passer par l'espace noyau.


Pour le processus 1234, vous pouvez obtenir sa carte mémoire en lisant séquentiellement /proc/1234/maps (un pseudo-fichier textuel) et lire la mémoire virtuelle par ex. read(2)-ing ou mmap(2)-ing segments appropriés du /proc/1234/mem pseudo-fichier fragmenté.

Cependant, je crois que vous ne pouvez pas éviter une sorte de synchronisation (peut-être avec ptrace(2), comme gdb fait), puisque le processus 1234 peut (et fait) modifier son espace d'adressage à tout moment (avec mmap &appels système associés).

La situation est différente si le processus surveillé 1234 n'est pas arbitraire, mais si vous pouviez l'améliorer pour communiquer d'une manière ou d'une autre avec le processus de surveillance.

Je ne suis pas sûr de comprendre pourquoi tu demandes ça. Et gdb est capable de watch un endroit sans arrêter le processus.


Si vous avez un accès root et que vous êtes sur un système Linux, vous pouvez utiliser le script Linux suivant (adapté de l'excellente réponse unix.stackexchange.com de Gilles et de la réponse donnée à l'origine dans la question ci-dessus mais incluant les erreurs de syntaxe et n'étant pas pythonic) :

#!/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

Si vous enregistrez ceci sous write_mem.py, vous pouvez l'exécuter (avec python2.6 ou 2.7) ou au début de python2.5 (si vous ajoutez from __future__ import with_statement ) comme :

sudo python write_mem.py 1234 > pid1234_memory_dump

pour vider la mémoire pid1234 dans le fichier pid1234_memory_dump.


Linux
  1. Comptage des fichiers ouverts par processus

  2. Malloc sur Linux sans surengagement

  3. délai d'attente sans tuer le processus dans bash

  4. Variables d'environnement d'un processus en cours d'exécution sous Unix ?

  5. Vider la mémoire d'un processus Linux dans un fichier

Construire des conteneurs à la main :l'espace de noms PID

Comment trouver le nom du processus à partir de son PID

-bash :fork :impossible d'allouer de la mémoire

umask actuel d'un processus avec <pid>

Utilisation maximale de la mémoire d'un processus

Comment l'utilisation de la mémoire est-elle signalée sous Linux ?