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

лабораторные Тимофеев / 3316_Кирейкова_Лабораторная2

.pdf
Скачиваний:
0
Добавлен:
01.06.2026
Размер:
500.29 Кб
Скачать

МИНОБРНАУКИ РОССИИ

САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА)

ОТЧЕТ

по Лабораторной работе №2

по дисциплине «Операционные системы»

«Управление памятью»

Выполнила:

Кирейкова С.А.

Группа: №3316

Преподаватель: Тимофеев А. В.

Санкт-Петербург

2025

Цель работы: исследовать механизмы управления виртуальной памятью

Win32.

Задание 2.1. Исследовать виртуальное адресное пространство процесса.

Указания к выполнению.

1. Создайте консольное приложение с меню (каждая выполняемая функция и/или операция должна быть доступна по отдельному пункту меню), которое выполняет:

− получение информации о вычислительной системе (функция

Win32 API – GetSystemInfo);

− определение статуса виртуальной памяти (функция Win32 API – GlobalMemoryStatus);

определение состояния конкретного участка памяти по заданному с клавиатуры адресу (функция Win32 API – VirtualQuery);

раздельное резервирование региона и передачу ему физической памяти в автоматическом режиме и в режиме ввода адреса начала региона (функция Win32 API – VirtualAlloc, VirtualFree);

одновременное резервирование региона и передача ему физической памяти в автоматическом режиме и в режиме ввода адреса начала региона (функция Win32 API – VirtualAlloc, VirtualFree);

запись данных в ячейки памяти по заданным с клавиатуры

адресам; − установку защиты доступа для заданного (с клавиатуры) региона

памяти и ее проверку (функция Win32 API – VirtualProtect).

2

Демонстрация работы приложения.

Меню:

Получение информации о вычислительной системе:

Определение статуса виртуальной памяти:

Автоматическое резервирование памяти:

Запись данных в ячейки памяти по заданным с клавиатуры адресам:

3

Чтение данных из памяти:

Установка защиты доступа для заданного региона памяти:

Проверка защиты доступа и определение состояния заданного региона памяти:

Код программы

#include <windows.h> #include <iostream> #include <iomanip> #include <string>

4

#include <limits> #include <vector>

using namespace std;

void ShowMenu() {

cout << "Menu:\n"; cout << "0. Exit\n";

cout << "1. Get System Info\n"; cout << "2. Get Memory Status\n"; cout << "3. Memory Region Status\n";

cout << "4. Reserve Memory Region (Manual)\n"; cout << "5. Reserve Memory Region (Automatic)\n"; cout << "6. Write Data to Memory\n";

cout << "7. Read Data from Memory\n"; cout << "8. Set Memory Protection\n"; cout <<

"9. Free Memory Region" << endl;

 

 

}

 

 

 

void PrintSystemInfo() {

 

 

SYSTEM_INFO sysInfo; GetSystemInfo(&sysInfo);

 

 

cout << "System Information:\n";

 

 

cout << "

Page size: " << sysInfo.dwPageSize << " bytes\n"; cout << "

Minimum

application address: "

 

 

<< sysInfo.lpMinimumApplicationAddress << "\n"; cout << "

Maximum

application address: "

 

 

<< sysInfo.lpMaximumApplicationAddress << "\n";

 

 

cout << "

Number of processors: " << sysInfo.dwNumberOfProcessors << "\n"; cout

<< "Processor Architecture: ";

 

 

switch (sysInfo.wProcessorArchitecture) {

 

 

case PROCESSOR_ARCHITECTURE_INTEL:

 

 

cout << "x86 (32-bit)" << endl; break;

 

 

case PROCESSOR_ARCHITECTURE_AMD64:

 

 

cout << "x64 (64-bit)" << endl; break;

 

 

case PROCESSOR_ARCHITECTURE_ARM:

 

 

cout << "ARM" << endl;

 

 

break; default:

 

 

cout << "Unknown" << endl;

 

 

break;

 

 

 

}

 

 

 

}

 

 

 

void PrintMemoryStatus() {

 

 

MEMORYSTATUSEX memStatus;

 

 

memStatus.dwLength = sizeof(memStatus); GlobalMemoryStatusEx(&memStatus);

 

cout << "Memory Status:\n";

 

 

cout << "

Memory in use: " << memStatus.dwMemoryLoad << "%\n";

 

 

cout << "

Total physical memory: " << memStatus.ullTotalPhys / 1024 / 1024 << "

MB\n";

 

 

 

cout << "

Available physical memory: " << memStatus.ullAvailPhys / 1024 / 1024

<< " MB\n";

 

 

cout << "

Total virtual memory: " << memStatus.ullTotalVirtual / 1024 / 1024 <<

" MB\n";

 

 

 

cout << "

Available virtual memory: " << memStatus.ullAvailVirtual / 1024 / 1024

<< " MB\n";

 

 

 

}

 

 

 

string GetMemoryState(DWORD state) { switch (state) {

case MEM_COMMIT: return "MEM_COMMIT"; case MEM_RESERVE: return "MEM_RESERVE"; case MEM_FREE: return "MEM_FREE"; default: return "Unknown";

}

}

5

cerr << "Failed to view the memory region!\n";
}
}
void ReserveManual() {
LPVOID lpAddress; SIZE_T dwSize;
cout << "Enter size of memory region to reserve (in bytes): "; cin >> dwSize; cout << "Enter memory address to reserve: "; cin >> hex >> lpAddress;
LPVOID lpMemory = VirtualAlloc(lpAddress, dwSize, MEM_COMMIT, PAGE_READWRITE); if (lpMemory == nullptr) {
cerr << "Failed to allocate memory region." << endl; return;
}
cout << "Memory region allocated at address: " << lpMemory << endl;
}
void ReserveAutomatic() {
LPVOID lpAddress; SIZE_T dwSize;
cout << "Enter size of memory region to reserve (in bytes): "; cin >> dwSize; LPVOID lpMemory = VirtualAlloc(nullptr, dwSize, MEM_COMMIT, PAGE_READWRITE); if (lpMemory == nullptr) {
cerr << "Failed to allocate memory region." << endl; return;
6
cout << "
}
else {
<< "
<< GetMemoryProtection(memInfo.AllocationProtect) << "\n";
cout << " Region Size: " << dec << memInfo.RegionSize << " bytes\n"; cout State: " << GetMemoryState(memInfo.State) << "\n";
cout << " Protect: " << GetMemoryProtection(memInfo.Protect) << "\n"; Type: " << GetMemoryType(memInfo.Type) << "\n";
string GetMemoryProtection(DWORD protect) { switch (protect) {
case PAGE_NOACCESS: return "PAGE_NOACCESS"; case PAGE_READONLY: return "PAGE_READONLY"; case PAGE_READWRITE: return "PAGE_READWRITE"; case PAGE_WRITECOPY: return "PAGE_WRITECOPY";
case PAGE_EXECUTE: return "PAGE_EXECUTE";
case PAGE_EXECUTE_READ: return "PAGE_EXECUTE_READ";
case PAGE_EXECUTE_READWRITE: return "PAGE_EXECUTE_READWRITE"; case PAGE_EXECUTE_WRITECOPY: return "PAGE_EXECUTE_WRITECOPY";
case PAGE_GUARD: return "PAGE_GUARD"; case PAGE_NOCACHE: return "PAGE_NOCACHE"; case PAGE_WRITECOMBINE: return "PAGE_WRITECOMBINE";
default: return "Unknown";
}
}
string GetMemoryType(DWORD type) { switch (type) {
case MEM_IMAGE: return "MEM_IMAGE"; case MEM_MAPPED: return "MEM_MAPPED"; case MEM_PRIVATE: return "MEM_PRIVATE"; default: return "Unknown";
}
}
void MemoryRegionStatus() { void* address;
cout << "Enter memory address to view the region status: "; cin >> hex >> address; if (cin.fail()) {
cerr << "Invalid memory address!" << endl; return;
}
MEMORY_BASIC_INFORMATION memInfo;
if (VirtualQuery(address, &memInfo, sizeof(memInfo)) == sizeof(memInfo))
{
cout << "Memory Region Information:\n";
cout << " Base Address: " << memInfo.BaseAddress << "\n"; cout << " Allocation Base: " << memInfo.AllocationBase << "\n"; cout << " Allocation
Protect: "

}

cout << "Memory region allocated at address: " << lpMemory << endl;

}

void ReadFromMemory() {

UINT_PTR address; HANDLE process; SIZE_T bytesread; const int buffersize = 256; char buffer[buffersize]; process = GetCurrentProcess();

cout << "Enter memory address to read from: "; cin >> hex >> address; if (cin.fail()) {

cerr << "Invalid memory address!" << endl; return;

}

if (ReadProcessMemory(process, (LPCVOID)address, buffer, buffersize, &bytesread) &&

bytesread > 0) {

cout << "Data has been successfully read from memory " << string(buffer, bytesread) << endl;

}

else {

cerr << "Failed to read data from memory! " << endl;

}

CloseHandle(process);

}

void WriteToMemory() {

UINT_PTR address; string data; HANDLE process;

cout << "Enter memory address for writing data: "; cin >> hex >> address; if (cin.fail()) {

cerr << "Invalid memory address!" << endl; return;

}

cout << "Enter data for writing: "; cin.ignore(); getline(cin, data);

process = GetCurrentProcess(); auto lpAddress = (LPVOID)address; SIZE_T byteswritten;

if (WriteProcessMemory(process, lpAddress, data.c_str(), data.size(), &byteswritten) && byteswritten == data.size()) {

cout << "Data has been successfully written to memory " << endl;

}

else {

cerr << "Error while writing data to memory! " << endl;

}

CloseHandle(process);

}

DWORD ChooseMemoryProtection() { int choice;

cout << "Choose memory protection:" << endl; cout << "1. PAGE_READONLY" << endl; cout << "2. PAGE_READWRITE" << endl;

cout << "3. PAGE_EXECUTE" << endl; cout << "4. PAGE_EXECUTE_READ" << endl;

cout << "5. PAGE_EXECUTE_READWRITE" << endl; cout << "6. PAGE_NOACCESS" << endl; cout << "Enter your choice: "; cin >> choice;

switch (choice) {

case 1: return PAGE_READONLY; case 2: return PAGE_READWRITE; case 3: return PAGE_EXECUTE;

case 4: return PAGE_EXECUTE_READ;

case 5: return PAGE_EXECUTE_READWRITE; case 6: return PAGE_NOACCESS; default:

7

cerr << "Invalid choice! Defaulting to PAGE_READWRITE." << endl; return PAGE_READWRITE;

}

}

void SetMemoryProtection() { UINT_PTR address;

DWORD protection = ChooseMemoryProtection(); DWORD oldProtect;

cout << "Enter memory address (in hexadecimal): "; cin >> hex >> address; if (cin.fail()) {

cerr << "Invalid memory address!" << endl; return;

}

SIZE_T size;

cout << "Enter size of the memory region (in bytes): "; cin >> dec >> size; if (cin.fail()) {

cerr << "Invalid size!" << endl; return;

}

LPVOID lpAddress = reinterpret_cast<LPVOID>(address);

if (VirtualProtect(lpAddress, size, protection, &oldProtect)) { cout << "Memory protection set successfully!" << endl;

cout << "Protection set to: " << hex << protection << "\n";

}

else {

cerr << "Failed to set memory protection.\n";

}

}

void FreeMemory() { LPVOID lpAddress; SIZE_T dwSize;

cout << "Enter memory address to free: "; cin >> lpAddress; cout << "Enter size to free: "; cin >> dwSize; VirtualFree(lpAddress, dwSize, MEM_DECOMMIT);

cout<< "Memory region freed " <<endl;

VirtualFree(lpAddress, dwSize, MEM_RELEASE); cout << "Memory region freed " <<

endl;

}

int main() {

int choice;

void* address = nullptr; SIZE_T size = 0; string data;

while (true) { ShowMenu();

cout << "Enter your choice: "; cin >> choice;

switch (choice) { case 1:

PrintSystemInfo(); break; case 2: PrintMemoryStatus(); break; case 3:

MemoryRegionStatus(); break; case 4:

ReserveManual(); break; case 5:

8

ReserveAutomatic(); break; case 6:

WriteToMemory(); break;

case 7: ReadFromMemory();

break; case 8: SetMemoryProtection();

break; case 9: FreeMemory();

break; case 10: return 0; default:

cerr << "Invalid choice. Please try again.\n"; break;

}

}

return 0;

}

Выводы по первой части

В ходе выполнения первой части были изучены принципы управления виртуальной памятью с помощью функций библиотеки Win32 API.

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

Программа позволяет пользователю получать информацию о системе,

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

9

Задание 2.2. Копирование файла с помощью операций перекрывающегося ввода-вывода.

Задание на проецируемый файлы. Два приложения – клиент и сервер.

Сервер создает файл на диске и проецирует его в память, далее записывает информацию и ждет, пока клиент не прочтет, затем отменяет проецирование и удаляет файл.

Клиент открывает файл, проецирует и ждет доступности чтения, затем читает и выводит результат, в завершении работы отменяет проецирование.

Сделать меню в каждой программе:

пункты меню Сервера – «выполнить проецирование», «записать данные», «завершить работу»;

пункты меню Клиента – «выполнить проецирование»,«прочитать данные», «завершить работу».

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

Как только файл спроецирован в память, к нему можно обращаться так, будто он целиком в нее загружен.

Когда несколько процессов используют mmap() для отображения одного и того же файла, они могут работать с общей памятью:

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

Если процессы используют флаг MAP_SHARED при вызове mmap() для отображения общего файла, то оба процесса будут работать с одними и теми же физическими страницами памяти (изменения, сделанные одним процессом в отображённой памяти, автоматически видны другому процессу, работающему с тем же файлом).Данный флаг влияет на взаимодействие между процессорам, совместное использованием ими памяти, синхронизацию изменений с файлом на диске.

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

Процесс проецирования:

10