2010-07-22 14 views
8

Estoy buscando un método para almacenar la memoria del proceso y restaurarla más adelante en ciertas condiciones.Parcheo de la memoria del proceso en tiempo de ejecución para restaurar el estado

...

preguntas realidad, yo he leído sobre él ... parece un gran reto!

Por lo tanto, vamos a analizar: La aplicación es un sistema distribuido, pero muchos procesos son apátridas (solicitar su estado a un servidor centralizado). Los procesos utilizan conexiones de red y memoria compartida para comunicarse con otros procesos.

El servidor central deberá guardar su estado por vertimiento su memoria proceso, que debe ser restaurada después de un ciertas condiciones. (1)

Conocí las funciones ReadProcessMemory y WriteProcessMemory, que permiten que el proceso se lea a sí mismo y sobrescriba la memoria ya asignada, ¿no es así? Entonces, lo que necesito es la dirección donde empiezo a leer/escribir, y el número de bytes para leer/escribir. Entonces ... ¿cuál es la dirección? Muchos códigos que he leído usan la dirección devuelta por VirtualAlloc, pero no sé si esto podría ser útil para mí.

que asumen que los segmentos ejecutables del proceso no están cambiando, por lo que no necesitan rojo/escrito. En tiempo de restauración, también podría suponer que todos los hilos de proceso están en la misma posición de ejecución cuando la memoria fue leída por el hilo principal.

Se mantiene la memoria de pila, y la memoria de pila, que son los segmentos de memoria lo que me interesa.

¿Es posible?

(1) es perfectamente legal para preguntar por qué estoy tratando de hacer esto. La razón es ... complicada, como de costumbre. Sin embargo, supongamos que la aplicación tiene un estado muy complicado, que requiere un algoritmo de ahorro de estado demasiado complejo. La otra alternativa (que está en el tema de análisis) es la implementación de un mecanismo logger/replay capaz de reproducir cada evento que ha contribuido al estado modificado.


Me vino a la mente el malloc & co. hook. Entonces puedo rastrear la memoria asignada por el proceso. Pero en realidad noté la estructura _CrtMemState, pero no sé si podría ser útil para mí.

Respuesta

8

ReadProcessMemory es para la lectura de la memoria de otro proceso . Dentro de un proceso, no es necesario; puede desreferenciar un puntero para leer la memoria dentro del mismo proceso.

Para encontrar los bloques de memoria en un proceso, puede utilizar VirtualQuery. Cada bloque se etiquetará con un estado, tipo, tamaño, etc. Aquí hay un código que escribí hace años para recorrer la lista de bloqueos de un proceso específico (usando VirtualQueryEx). Utiliza el VirtualQuery de la misma manera, excepto que no tiene que especificar un proceso, ya que siempre recorre el proceso en el que se ejecuta.

#define WIN32_LEAN_AND_MEAN 
#include <windows.h> 
#include <stdio.h> 
#include <stdlib.h> 

unsigned long usage; 

void show_modules(HANDLE process) { 

    unsigned char *p = NULL; 
    MEMORY_BASIC_INFORMATION info; 

    for (p = NULL; 
     VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info); 
     p += info.RegionSize) 
    { 
     printf("%#10.10x (%6uK)\t", info.BaseAddress, info.RegionSize/1024); 

     switch (info.State) { 
     case MEM_COMMIT: 
      printf("Committed"); 
      break; 
     case MEM_RESERVE: 
      printf("Reserved"); 
      break; 
     case MEM_FREE: 
      printf("Free"); 
      break; 
     } 
     printf("\t"); 
     switch (info.Type) { 
     case MEM_IMAGE: 
      printf("Code Module"); 
      break; 
     case MEM_MAPPED: 
      printf("Mapped  "); 
      break; 
     case MEM_PRIVATE: 
      printf("Private "); 
     } 
     printf("\t"); 

     if ((info.State == MEM_COMMIT) && (info.Type == MEM_PRIVATE)) 
      usage +=info.RegionSize; 

     int guard = 0, nocache = 0; 

     if (info.AllocationProtect & PAGE_NOCACHE) 
      nocache = 1; 
     if (info.AllocationProtect & PAGE_GUARD) 
      guard = 1; 

     info.AllocationProtect &= ~(PAGE_GUARD | PAGE_NOCACHE); 

     switch (info.AllocationProtect) { 
     case PAGE_READONLY: 
      printf("Read Only"); 
      break; 
     case PAGE_READWRITE: 
      printf("Read/Write"); 
      break; 
     case PAGE_WRITECOPY: 
      printf("Copy on Write"); 
      break; 
     case PAGE_EXECUTE: 
      printf("Execute only"); 
      break; 
     case PAGE_EXECUTE_READ: 
      printf("Execute/Read"); 
      break; 
     case PAGE_EXECUTE_READWRITE: 
      printf("Execute/Read/Write"); 
      break; 
     case PAGE_EXECUTE_WRITECOPY: 
      printf("COW Executable"); 
      break; 
     } 

     if (guard) 
      printf("\tguard page"); 
     if (nocache) 
      printf("\tnon-cachable"); 
     printf("\n"); 
    } 
} 

int main(int argc, char **argv) { 

    int pid; 

    if (argc != 2) { 
     fprintf(stderr, "Usage: %s <process ID>", argv[0]); 
     return 1; 
    } 

    sscanf(argv[1], "%i", &pid); 

    HANDLE process = OpenProcess( 
     PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 
     false, 
     pid); 

    show_modules(process); 
    printf("Total memory used: %luKB\n", usage/1024); 
    return 0; 
}   
+0

Gran ejemplo. En realidad funciona, pero para casos muy limitados. ¡Gracias! – Luca

+0

Esto es como '' 'cat/proc/pid/maps''' en Linux, excepto que con este código no se sabe a qué módulo pertenece cada bloque de memoria. ¿Es posible obtener esa información de alguna manera? – alexandernst

+0

Ah, acabo de encontrar cómo hacerlo :) '' 'GetModuleFileNameA ((HINSTANCE) mbi.AllocationBase, szModName, _countof (szModName));' '' – alexandernst

1

La memoria de proceso no representa todo el estado del proceso. El sistema operativo retendrá objetos en nombre de su proceso (por ejemplo, identificadores de archivos, objetos de sincronización, etc.) en lugares como grupos no paginados que están fuera del alcance de su proceso.

Creo que será mejor que refactorice hasta que pueda serializar y deserializar el estado relevante con un esfuerzo manejable.

+0

Lo entiendo, pero suponiendo que no se crean ni eliminan nuevos identificadores y la modificación de ellos no es significativa para el estado del proceso, creo que esto podría funcionar. Por supuesto que estoy de acuerdo con la serialización. Debería ser el camino ... – Luca

Cuestiones relacionadas