Исправление памяти процесса выполнения для восстановления состояния - PullRequest
8 голосов
/ 23 июля 2010

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

...

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

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

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

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

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

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

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

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


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

Ответы [ 2 ]

8 голосов
/ 23 июля 2010

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;
}        
1 голос
/ 23 июля 2010

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

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

...