2010-07-22 3 views
8

Я ищу способ хранения памяти процесса и позже его восстановить при определенных условиях.Патч памяти для процесса восстановления для восстановления состояния

...

На самом деле я прочитал вопросы об этом ... Это кажется большой проблемой!

Итак, давайте проанализируем: приложение является распределенным, но многие процессы не имеют состояния (запрашивают их состояние на централизованный сервер). Процессы используют сетевые подключения и общую память для связи с другими процессами.

Центральный сервер должен сохранить свое состояние, сбросив его память процесса, которое должно быть восстановлено позже в определенных условиях. (1)

Я знаю о функциях ReadProcessMemory и WriteProcessMemory, которые позволяют процессу читать себя и перезаписывать уже выделенную память, не так ли? Итак, мне нужен адрес, где я начинаю читать/писать, и количество байтов для чтения/записи. Итак ... какие адреса? Многие прочитанные мной коды используют адрес, возвращаемый VirtualAlloc, но я не знаю, может ли это быть полезным для меня.

Я предполагаю, что исполняемые сегменты процесса не меняются, поэтому они не нуждаются в красном/письменном виде. Во время восстановления я также мог предположить, что все потоки процессов находятся в одной и той же позиции выполнения, когда память была прочитана основным потоком.

Он остается в памяти стека, и память кучи, которые являются сегменты памяти, что я заинтересован в.

Возможно ли это?

(1) Совершенно законно спрашивать, почему я пытаюсь это сделать. Причина ... сложная, как обычно. Однако скажите, что приложение имеет очень сложное состояние, которое требует слишком сложного алгоритма экономии состояний. Другой альтернативой (которая является предметом анализа) является реализация механизма регистрации/воспроизведения, способного воспроизводить каждое событие, которое способствовало измененному состоянию.


Мне пришло в голову malloc & co. hook. Поэтому я могу отслеживать память, выделенную процессом. Но на самом деле я заметил структуру _CrtMemState, но я не знаю, может ли она быть полезной для меня.

ответ

8

ReadProcessMemory предназначен для чтения памяти другой процесс. Внутри процесса это не нужно - вы можете просто разыменовать указатель на чтение памяти в рамках одного и того же процесса.

Чтобы найти блоки памяти в процессе, вы можете использовать VirtualQuery. Каждый блок будет помечен как состояние, тип, размер и т. Д. Вот несколько кодов, которые я написал много лет назад, чтобы перейти к списку блоков для указанного процесса (используя VirtualQueryEx). Вы используете VirtualQuery почти так же, за исключением того, что вам не нужно указывать процесс, так как он всегда выполняет процесс, в котором работает.

#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

Отличный пример. Это действительно работает, но для очень ограниченных случаев. Спасибо! – Luca

+0

Это как '' '' cat/proc/pid/maps''' в Linux, за исключением того, что с этим кодом вы не знаете, к какому модулю принадлежит каждый блок памяти. Возможно ли получить такую ​​информацию? – alexandernst

+0

А, я только что нашел, как это сделать :) '' 'GetModuleFileNameA ((HINSTANCE) mbi.AllocationBase, szModName, _countof (szModName));' '' – alexandernst

1

Память процесса не отражает все состояние процесса. Операционная система будет хранить объекты от имени вашего процесса (например, файлы, объекты синхронизации и т. Д.) В таких местах, как непонятый пул, которые выходят за рамки вашего процесса.

Я думаю, вам будет лучше рефакторинг, пока вы не сможете сериализовать и десериализовать соответствующее состояние с управляемыми усилиями.

+0

Я понимаю это, но при условии, что никакие новые дескрипторы не создаются/удаляются и модификация для них не имеет смысла для состояния процесса, я думаю, что это может сработать. Конечно, я согласен с сериализацией. Это должно быть так ... – Luca

Смежные вопросы