GNU/Linux >> Linux Esercitazione >  >> Linux

Leggere la memoria del processo vivente senza interromperla

Dalla versione 3.2 del kernel. Puoi utilizzare la chiamata di sistema process_vm_readv per leggere la memoria del processo senza interruzioni.

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

Queste chiamate di sistema trasferiscono i dati tra lo spazio degli indirizzi del processo chiamante ("il processo locale") e il processo identificato da pid ("il processo remoto"). I dati si spostano direttamente tra gli spazi degli indirizzi dei due processi, senza passare attraverso lo spazio del kernel.


Per il processo 1234 puoi ottenere la sua mappa di memoria leggendo in sequenza /proc/1234/maps (uno pseudo-file testuale) e leggere la memoria virtuale ad es. read(2)-ing o mmap(2)-ing segmenti appropriati di /proc/1234/mem pseudo-file sparse.

Tuttavia, credo che tu non possa evitare un qualche tipo di sincronizzazione (forse con ptrace(2), come gdb lo fa), poiché il processo 1234 può (e lo fa) alterare il suo spazio di indirizzi in qualsiasi momento (con mmap e chiamate di sistema correlate).

La situazione è diversa se il processo monitorato 1234 non è arbitrario, ma se potessi migliorarlo per comunicare in qualche modo con il processo monitorato.

Non sono sicuro di capire perché me lo chiedi. E gdb è in grado di watch qualche posizione senza interrompere il processo.


Se hai accesso root e sei su un sistema Linux, puoi usare il seguente script linux (adattato dall'eccellente risposta unix.stackexchange.com di Gilles e la risposta originariamente data nella domanda sopra ma includendo SyntaxErrors e non essendo 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

Se lo salvi come write_mem.py, puoi eseguirlo (con python2.6 o 2.7) o all'inizio di python2.5 (se aggiungi from __future__ import with_statement ) come:

sudo python write_mem.py 1234 > pid1234_memory_dump

per eseguire il dump della memoria pid1234 nel file pid1234_memory_dump.


Linux
  1. Costruire contenitori a mano:lo spazio dei nomi PID

  2. Non riesci a uccidere il processo Gedit dal suo Pid?

  3. Linux:ottenere informazioni sull'utilizzo della memoria di un processo da /proc/pid/smaps?

  4. Definizione di una variabile con o senza esportazione

  5. Utilizzo della memoria del processo corrente in C

Come trovare il nome del processo dal suo PID

Umask corrente di un processo con <pid>

Come viene riportato l'utilizzo della memoria in Linux?

Variabili d'ambiente di un processo in esecuzione su Unix?

Scarica la memoria di un processo Linux su file

Come ottenere il pid del processo appena avviato