Лабораторные работы / Windows лаб 1-4 / lab3_var2_kod
.pdfЛР 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