que kcore 128t linux memory

linux - 128t - Lectura de la memoria del proceso en vivo sin interrumpirla(/ proc/kcore es una opción)



/proc/kcore que es (5)

Desde la versión 3.2 del kernel. Puede utilizar la llamada al sistema process_vm_readv para leer la memoria del proceso sin interrupción.

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

Estas llamadas al sistema transfieren datos entre el espacio de direcciones del proceso de llamada ("el proceso local") y el proceso identificado por pid ("el proceso remoto"). Los datos se mueven directamente entre los espacios de direcciones de los dos procesos, sin pasar por el espacio del kernel.

Me gustaría explorar la memoria de un proceso vivo, y cuando lo hago, el proceso no debe ser perturbado, por lo que adjuntar gdb al proceso (que lo detendría) no es una opción. Por lo tanto, me gustaría obtener esta información de / proc / kcore (si conoce otra forma de hacerlo, hágamelo saber). Así que hice un pequeño experimento. Creé un archivo llamado TEST con solo "EXTRATESTEXTRA" dentro. Entonces lo abrí con menos

$ less TEST

Obtuve el PID de este proceso con

$ ps aux | grep TEST user 7785 0.0 0.0 17944 992 pts/8 S+ 16:15 0:00 less TEST user 7798 0.0 0.0 13584 904 pts/9 S+ 16:16 0:00 grep TEST

Y luego utilicé este script para crear un volcado de todos los archivos:

#!/bin/bash grep rw-p /proc/$1/maps | sed -n ''s/^/([0-9a-f]*/)-/([0-9a-f]*/) .*$//1 /2/p'' | while read start stop; do gdb --batch --pid $1 -ex "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; done

(Lo encontré en este sitio https://serverfault.com/questions/173999/dump-a-linux-processs-memory-to-file )

$ sudo ./dump_all_pid_memory.sh 7785

Después de esto, busqué "TRATESTEX" en todos los archivos volcados:

$ grep -a -o -e ''...TRATESTEX...'' ./*.dump ./7785-00624000-00628000.dump:HEXTRATESTEXTRA ./7785-00b8f000-00bb0000.dump:EXTRATESTEXTRA ./7785-00b8f000-00bb0000.dump:EXTRATESTEXTRA

Así que llegué a la conclusión de que debe haber una ocurrencia de esta cadena en algún lugar entre 0x00624000 y 0x00628000. Por lo tanto, convertí las compensaciones en números decimales y usé dd para obtener la memoria de / proc / kcore:

$ sudo dd if="/proc/kcore" of="./y.txt" skip="0" count="1638400" bs=1

Para mi sorpresa, el archivo y.txt estaba lleno de ceros (no encontré la cadena que estaba buscando).

Como sorpresa adicional, ejecuté una prueba similar al mismo tiempo con un archivo de prueba diferente y encontré que la otra cadena de prueba que estaba usando (ambos procesos con menos se estaban ejecutando al mismo tiempo) se debe encontrar en la misma ubicación (la el dumping y el greping dieron la misma compensación). Así que debe haber algo que no entiendo claramente.

  • ¿No se supone que el / proc / pid / maps muestre el desplazamiento de la memoria (es decir, si se dice que "XXX" está en el desplazamiento 0x10, otro programa no podría usar el mismo desplazamiento? ¿Estoy en lo correcto? fuente de mi segunda sorpresa)

  • ¿Cómo puedo leer / proc / kmap para obtener la memoria que pertenece a un proceso que es un pid que conozco?

EDITAR - para futuros tropiezos (ver la respuesta a continuación primero)

Para resumir las respuestas y agregar mi propio comentario: - / proc / pid / maps muestra las partes de la memoria A medida que EL PROCESO LO VE (diferente para cada proceso, busque la asignación de memoria en Linux), por lo que pueden parecer procesos diferentes. usando la misma parte de la memoria (como se ve desde su perspectiva). Puede leer las partes especificadas aquí desde / proc / pid / mem como superusuario (o un proceso principal como gdb lo hace con ptrace) - la memoria en /proc/kcore no es lo mismo que la memoria desde la perspectiva del proceso en /proc/pid/mem - para buscar la memoria del proceso en /proc/kcore , uno tendría que averiguar cómo se asigna la memoria del proceso a la memoria del kernel (muchas cosas sucias y lentas) Para obtener la memoria del proceso, primero lea qué regiones de /proc/pid/maps tiene permiso para leer / escribir desde / a y luego copiar y copiar las regiones de /proc/pid/mem . La siguiente secuencia de comandos descarga todas las regiones grabables (fuente: https://unix.stackexchange.com/questions/6301/how-do-i-read-from-proc-pid-mem-under-linux ). EDITAR: El script de python de trabajo revisado se mueve a su propia respuesta, por lo que se puede comentar de forma distinta a la pregunta.


Logré esto emitiendo el siguiente comando

[root @ stage1 ~] # echo "Uso de memoria para PID [MySql]:"; para mem en {Privado, Rss, Compartido, Intercambio, Pss}; haga grep $ mem / proc / ps aux |grep mysql |awk ''{print $2}''|head -n 1 / smaps | awk -v mem_type = "$ mem" ''{i = i + $ 2} END {print mem_type, "uso de memoria:" i}''; listo

Resultado de salida

Uso de memoria para PID [MySql]:

Uso de memoria privada: 204

Uso de memoria rss: 1264

Uso de memoria compartida: 1060

Uso de memoria de intercambio: 0

Uso de memoria pss: 423


Para el proceso 1234, puede obtener su mapa de memoria leyendo secuencialmente /proc/1234/maps (un pseudoarchivo textual) y leer la memoria virtual, por ejemplo, read(2) -ing o mmap(2) -ing segmentos apropiados del /proc/1234/mem spse pseudo-file.

Sin embargo, creo que no se puede evitar algún tipo de sincronización (tal vez con ptrace(2) , como hace gdb ), ya que el proceso 1234 puede (y lo hace) alterar su espacio de direcciones en cualquier momento (con mmap y syscalls relacionados).

La situación es diferente si el proceso supervisado 1234 no es arbitrario, pero si pudiera mejorarlo para comunicarse de alguna manera con el proceso de supervisión.

No estoy seguro de entender por qué preguntas esto. Y gdb puede watch alguna ubicación sin detener el proceso.


Si tiene acceso a la raíz y está en un sistema Linux, puede usar la siguiente secuencia de comandos de Linux (adaptada de la excelente respuesta de Gilles en unix.stackexchange.com y la respuesta que se dio originalmente en la pregunta anterior, pero que incluye SyntaxErrors y no es 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 guarda esto como write_mem.py, puede ejecutar esto (con python2.6 o 2.7) o temprano en python2.5 (si lo agrega from __future__ import with_statement ) como:

sudo python write_mem.py 1234 > pid1234_memory_dump

para volcar la memoria pid1234 en el archivo pid1234_memory_dump.


Tendrá que usar / proc // mem para leer la memoria de proceso, no recomendaría intentar leer / proc / kcore o cualquiera de las funciones de memoria del kernel (lo que requiere mucho tiempo)