Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
11
Добавлен:
26.02.2022
Размер:
139.07 Кб
Скачать

ЛР 3 Вариант 2 Использование виртуальной памяти в приложениях

Задание варианта 2

1. Введите диапазон адресов и выведите на экран информацию о:

1.1 состоянии регионов виртуального адресного пространства в данном диапазоне (свободен, зарезервирован или выделен).

1.2 состоянии страниц виртуальной памяти в данном регионе (нет доступа, только чтение, чтение и запись). 1.3 количестве регионов в данном диапазоне адресов и количестве страниц в каждом регионе.

2. Выведите на экран карту памяти данного процесса (информацию о каждом регионе в виртуальном адресном пространстве текущего процесса).

Выполнение

#define NOMINMAX #include <iostream> #include <string> #include <iomanip> #include <limits> #include <windows.h>

using namespace std;

#define PAGE_ALIGN(addr, size) ((uintptr_t)addr & ~((size_t)size - 1))

//функция нажатия клавиши без эха, возвращает ее код

//аналог нестандартной _getch()

char Getch()

{

static HANDLE hStdOut = GetStdHandle(STD_INPUT_HANDLE); // получаем дескриптор ввода

DWORD mode;

GetConsoleMode(hStdOut, &mode); // получаем текущий режим ввода

// устанавливаем новый режим: отключаем обязательное нажатие <Enter> для ввода и эхо

SetConsoleMode(hStdOut, mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT));

char result = 0; DWORD nread;

ReadConsole(hStdOut, &result, 1, &nread, nullptr); // читаем символ SetConsoleMode(hStdOut, mode); // устанавливаем старый режим return result;

}

//пауза void Pause()

{

cout << "Press any key to continue...\n" << endl; Getch(); // пауза до нажатия клавиши

}

//проверка состояния региона

char GetState(DWORD state)

{

if (state == MEM_COMMIT)

1

return 'C'; // выделено

if (state == MEM_RESERVE) return 'R'; // зарезервировано

if (state == MEM_FREE) return 'F'; // свободно

return 0;

}

// возвращает строку-описание аттрибутов доступа string GetAccess(DWORD prot)

{

string result;

switch (prot & 0x00FF)

{

case PAGE_EXECUTE: // доступ на исполнение result = "--X-";

break;

case PAGE_EXECUTE_READ: // исполнение/чтение result = "R-X-";

break;

case PAGE_EXECUTE_READWRITE: // исполнение/чтение/запись result = "RWX-";

break;

case PAGE_EXECUTE_WRITECOPY: // исполнение/чтение/копирование при записи result = "R-XC";

break;

case PAGE_NOACCESS: // нет result = "----";

break;

case PAGE_READONLY: // чтение result = "R---";

break;

case PAGE_READWRITE: // чтение/запись result = "RW--";

break;

case PAGE_WRITECOPY: // чтение/копирование при записи result = "R--C";

break;

default: // недоступно return " "; break;

}

result += (prot & PAGE_GUARD) ? 'G' : '-'; // Guard

result += (prot & PAGE_NOCACHE) ? 'N' : '-'; // некэшируемый

result += (prot & PAGE_WRITECOMBINE) ? 'Q' : '-'; // запись с объединением return result;

}

// тип региона

string GetType(DWORD type)

{

switch (type)

{

case MEM_IMAGE: // образ return "image";

case MEM_MAPPED: // отображение в память return "mapped";

case MEM_PRIVATE: // частный (принадлежит процессу) return "private";

2

default: // неиспользуемый return "unused";

}

}

// вспомогательная ф-я ввода значения адреса из диапазона [low; high] uintptr_t GetAddress(const char* prompt, uintptr_t low, uintptr_t high)

{

uintptr_t result; while (true)

{

cout << prompt;

cout << "(unsigned hex number from range [" << hex << showbase << low << "; " << high << "]): "; cin >> hex >> result;

if (!cin)

{// ввели не число cin.clear();

cin.ignore(numeric_limits<streamsize>::max(), '\n'); // удаляем введенные символы

cout << "Wrong input!\n";

}

else if(result < low || result > high) { // не из диапазона

cout << "Wrong address!\n";

}

else

{// ввод корректный break;

}

}

return result;

}

int main()

{

SYSTEM_INFO si;

GetSystemInfo(&si); // получаем системную информацию auto page_size = si.dwPageSize; // размер страницы

auto min_address = reinterpret_cast<uintptr_t>(si.lpMinimumApplicationAddress); // манимальный адрес auto max_address = reinterpret_cast<uintptr_t>(si.lpMaximumApplicationAddress); // максимальный

// вводим диапазон адресов в шестнадцатеричном виде, которые будем просматривать

cout << "Enter addresses from range [" << hex << showbase << min_address << "; " << max_address << "]:\n"; auto lower = GetAddress("Lower bound ", min_address, max_address);

auto higher = GetAddress("Higher bound ", lower, max_address);

// выравниваем по границе страницы lower = PAGE_ALIGN(lower, page_size); higher = PAGE_ALIGN(higher, page_size);

cout << "\nLegend:\n"

<<"\tState:\tFree, Reserved, Committed;\n"

<<"\tAccess:\tReadable, Writable, eXecutable, Copy-on-write, Guard,\n"

<<"\t\tNo cache, write combine (Q), no access (-------);\n"

<<"\t\tempty space indicates no access to page protection info.\n\n";

MEMORY_BASIC_INFORMATION info{}; size_t region_count = 0;

// вывод таблицы регионов

cout << " Address" << " Size" << " Pages" << " Used" << " State" << " Access " << " Type\n"; for (uintptr_t p = lower; p < higher; p += info.RegionSize)

3

{

if (VirtualQuery((void*)p, &info, sizeof info) == 0) // запрос информации о регионе break;

++region_count; // считаем количество регионов

cout << setw(10) << hex << showbase << p; // вывод адреса в шестнадцатеричном виде cout << dec << setw(12) << info.RegionSize; // размер в байтах

cout << setw(10) << info.RegionSize / page_size; // количество страниц cout << (info.State == MEM_FREE ? " no " : " yes "); // используется ли? cout << " " << GetState(info.State) << " "; // состояние

cout << GetAccess(info.AllocationProtect); // доступ cout << " " << GetType(info.Type) << '\n'; // тип

}

cout << "\nTotal number of regions: " << region_count << "\n\n"; // выводим сколько регионов всего Pause();

return 0;

}

4

Соседние файлы в папке Windows лаб 1-4