Главная страница
Навигация по странице:

  • Взаимоисключения

  • ReleaseMutex

  • ЗАДАНИЕ 1 Постановка задачи

  • Лабораторная работа № 3

  • Теоретические сведения Виртуальное адресное пространство и физическая память

  • Состояние страниц и атрибуты защиты

  • Границы выделения памяти

  • Регионы в адресном пространстве

  • VirtualFree

  • Освобождение памяти

  • Работа со страницами

  • VirtualQuery

  • Системное_программирование. Практикум для студентов специальностей 140 01 02 Информационные системы и технологии


    Скачать 1.66 Mb.
    НазваниеПрактикум для студентов специальностей 140 01 02 Информационные системы и технологии
    Дата02.09.2020
    Размер1.66 Mb.
    Формат файлаpdf
    Имя файлаСистемное_программирование.pdf
    ТипПрактикум
    #136562
    страница2 из 6
    1   2   3   4   5   6
    Критические секции
    Критическая секция (critical section) – это небольшой участок кода, требующий монопольного доступа к каким-то общим данным.
    Она позволяет сделать так, чтобы единовременно только один по- ток получал доступ к определенному ресурсу.
    CRITICAL_SECTION g_cs;
    //
    инициализация структуры CRITICAL_SECTION
    InitializeCriticalSection(&g_cs);
    DWORD WINAPI FunctionThread(LPVOID)
    {
    //начало работы с критической секцией
    EnterCriticalSection(&g_cs);
    //конец работы с критической секцией
    LeaveCriticalSection(&g_cs);
    }

    17
    Взаимоисключения
    Объекты ядра "мьютексы" гарантируют потокам взаимоисклю- чающий доступ к единственному ресурсу.
    Мьютекс создается функцией CreateMutex(): m_hMutex1 = CreateMutex(
    NULL
    , //указатель на структуру SECURITY_ATTRIBUTES
    FALSE,
    // определяет начальное состояние мьютекса
    NULL // адрес строки (с нулевым символом в конце),
    // идентифицирующей мьютекс
    );
    Функция ReleaseMutex() переводит объект-мьютекс из занятого состояния в свободное.
    События
    События – разновидность объектов ядра. Они содержат счетчик числа пользователей (как и все объекты ядра) и две булевы пере- менные: одна сообщает тип данного объекта-события, другая – его состояние (свободен или занят).
    События просто уведомляют об окончании какой-либо операции.
    Объекты-события бывают двух типов: со сбросом вручную (manual- reset events) и с автосбросом (auto-reset events).
    Первые позволяют возобновлять выполнение сразу нескольких ждущих потоков, вто- рые – только одного.
    Пример создания и использования событий приведен ниже.
    HANDLE g_hEvent1,g_hEvent2,g_hEvent3;
    //
    создание события с автосбросом, свободное g_hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL);
    //
    создание события с автосбросом, занятое g_hEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);
    //ожидание освобождения события
    WaitForSingleObject(g_hEvent2, INFINITE);
    //установить g_hEvent2 в занятое состояние
    ResetEvent(g_hEvent2);
    //установить g_hEvent3 в свободное состояние
    SetEvent(g_hEvent3);

    18
    Семафоры
    Объекты ядра "семафор" используются для учета ресурсов. Как и все объекты ядра, они содержат счетчик числа пользователей, но, кроме того, поддерживают два 32-битных значения со знаком: одно определяет максимальное число ресурсов (контролируемое семафо- ром), другое используется как счетчик текущего числа ресурсов.
    Пример создания и использования семафора приведен ниже.
    HANDLE hSem1,hSem2,hSem3; hSem1 = CreateSemaphore(
    NULL, // указатель на структуру SECURITY_ATTRIBUTES
    1,
    // сколько из ресурсов доступно изначально
    1,
    //
    максимальное значение счетчика
    NULL
    // адрес строки, идентифицирующей семафор); hSem2 = CreateSemaphore(NULL, 0, 1, NULL);
    //создание занятого семофора
    WaitForSingleObject(hSem2, INFINITE);
    //
    увеличение значение счетчика текущего числа ресурсов
    ReleaseSemaphore( hSem3,
    //указатель на объекта ядра «семафор»
    1,
    // на сколько изменить счетчик
    NULL); // исходное значение счетчика ресурсов
    ЗАДАНИЕ
    1
    Постановка задачи
    В буфере имеется N записей типа Type. К этим записям на чте- ние и на запись обращаются m потоков. Каждый из потоков может изменить содержимое записи. Существует поток I, который отоб- ражает на мониторе изменённые записи. Каждую запись может из- менить только I-тый поток. Когда поток I отобразит последнюю из- мененную запись, остальные потоки могут продолжать модифици- ровать записи. Поток I запускается по нажатию клавиш ALT+I.
    Реализовать задачу. Тип записи задается преподавателем.
    1
    Данное задание выполняется студентами, которые претендуют на оценку
    «
    отлично»

    19
    Лабораторная работа № 3
    УПРАВЛЕНИЕ ПАМЯТЬЮ В WINDOWS
    Цель работы: Изучить основы распределения и управления памятью в Windows.
    Изучаемые вопросы
    1.
    Виртуальное адресное пространство: a.
    Виртуальное адресное пространство и физическая память. b.
    Состояние страниц. c.
    Атрибуты защиты. d.
    Границы выделения памяти. e.
    Регионы в адресном пространстве.
    2.
    Работа с виртуальной памятью: a.
    Выделение памяти. b.
    Освобождение памяти. c.
    Изменение атрибутов защиты. d.
    Блокировка физической памяти RAM. e.
    Стек потока.
    3.
    Кучи.
    4.
    Стандартные библиотечные функции языка С.
    Постановка задачи
    Разработать приложение, которое предоставляет пользователю возможность управлять памятью в Windows, получать системную информацию о состоянии физической и виртуальной памяти, а также управлять выделением и освобождением виртуальной памяти.
    В программе предусмотреть использование различных видов па- мяти:
    1. Статически распределяемой.
    2. Стековой памяти.
    3. Динамически распределяемой памяти.
    4. Регионов виртуальной памяти.

    20
    Теоретические сведения
    Виртуальное адресное пространство и физическая память
    Виртуальное адресное пространство каждого процесса значи- тельно больше всей физической памяти, доступной для всех про- цессов. Общий объем памяти, доступной для всех исполняемых процессов, является суммой физической памяти и свободного места на диске, доступного для файла подкачки (paging file) – файла на диске, используемого для увеличения объема физической памяти.
    Реальная физическая память и виртуальное адресное пространство для каждого процесса организованны в страницы (pages) – модули памяти, чей размер зависит от процессора. Например, для процес- соров семейства х86 размер страницы памяти равен 4 Кбайт.
    Состояние страниц и атрибуты защиты
    Страницы виртуального адресного пространства процессов мо- гут находиться в одном из трех состояний:

    свободное (free) – свободная страница в данный момент не доступна, но ей можно передать физическую память или зарезерви- ровать;

    зарезервированное (reserved) – зарезервированная страница – это блок виртуального адресного пространства процесса, который был зарезервирован для более позднего использования. Процесс не имеет доступа к зарезервированной странице и с ней не связана фи- зическая память. Зарезервированная страница резервирует область виртуального адресного пространства, которая в дальнейшем не может быть использована другой функцией размещения памяти.

    фиксированное (committed) – фиксированная страница – это такая страница, для которой выделена физическая память (в ОЗУ или на диске). Она может быть защищена от доступа других про- цессов, может быть доступна только для чтения или для чтения и записи.
    На рисунке 3.1 продемонстрировано окно приложения по рас- пределению памяти процесса в Windows. Ниже приведен код для определения состояния страниц.

    21
    Рис. 3.1. Адресное пространство процесса
    Пример.
    //состояние страниц switch(mem_info2.State)
    { case MEM_COMMIT: i+=sprintf(buf+i," COMMIT "); break; case MEM_FREE: i+=sprintf(buf+i," FREE "); break; case MEM_RESERVE: i+=sprintf(buf+i," RESERVE"); break; default: i+=sprintf(buf+i," UNKNOWN"); break;
    }

    22
    На рисунке 3.2 представлен интерфейс для выбора атрибутов защиты страниц памяти, где:
    — PAGE_NOACCESS – попытки чтения, записи или исполнения содержимого памяти в этом регионе вызывают нарушение доступа;
    — PAGE_READONLY – попытки записи или исполнения со- держимого памяти в этом регионе вызывают нарушение доступа;
    — PAGE_READWRITE – попытки исполнения содержимого па- мяти в этом регионе вызывают нарушение доступа;
    — PAGE_EXECUTE – попытки чтения или записи в память это- го региона вызывают нарушение доступа;
    — PAGE_EXECUTE_READ – попытки записи в память этого ре- гиона вызывают нарушение доступа;
    — PAGE_EXECUTE_READWRITE – данный регион допускает любые операции;
    — PAGE_GUARD – страницы в этом регионе становятся защит- ными. Попытки прочитать или записать в защитную страницу при- ведут к возникновению исключительной ситуации и к сбросу за- щитного состояния. Таким образом защитная страница может слу- жить одноразовым сигналом. Комбинируется с любыми атрибутами
    (кроме PAGE_NOACCESS);
    — PAGE_NOCACHE – устанавливает невозможность кэширова- ния зафиксированной области страниц. Комбинируется с любыми атрибутами (кроме PAGE_NOACCESS);

    PAGE_WRITECOPY (для функции VirtualProtect) – попытки исполнения содержимого памяти в этом регионе вызывают наруше- ние доступа. Запись в память этого региона приводит к тому, что процессу предоставляется «личная» копия данной страницы физи- ческой памяти;

    PAGE_EXECUTE_WRITECOPY (для функции VirtualProtect) – данный регион допускает любые операции. Запись в память этого региона приводит к тому, что процессу предоставляется «личная» копия данной страницы физической памяти.

    23
    Рис. 3.2.. Выбор атрибута защиты памяти
    Отдельным страницам физической памяти, выделяемым функ- цией VirtualAlloc, можно определить атрибуты защиты, что приве- дено в нижележащем коде.
    VirtualQuery(pMemory, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)); switch(memInfo.Protect)
    { case PAGE_EXECUTE:
    SendDlgItemMessage(hDlg, IDC_RADIO1, BM_SETCHECK,
    BST_CHECKED, NULL); break; case PAGE_EXECUTE_READ:
    SendDlgItemMessage(hDlg, IDC_RADIO2, BM_SETCHECK,
    BST_CHECKED, NULL); break; case PAGE_EXECUTE_READWRITE:
    SendDlgItemMessage(hDlg, IDC_RADIO3, BM_SETCHECK,
    BST_CHECKED, NULL); break; case PAGE_EXECUTE_WRITECOPY:
    SendDlgItemMessage(hDlg, IDC_RADIO4, BM_SETCHECK,
    BST_CHECKED, NULL); break; case PAGE_NOACCESS:
    SendDlgItemMessage(hDlg, IDC_RADIO5, BM_SETCHECK,
    BST_CHECKED, NULL); break; case PAGE_READONLY:
    SendDlgItemMessage(hDlg, IDC_RADIO6, BM_SETCHECK,
    BST_CHECKED, NULL); break; case PAGE_READWRITE:

    24
    SendDlgItemMessage(hDlg, IDC_RADIO7, BM_SETCHECK,
    BST_CHECKED, NULL); break; case PAGE_WRITECOPY:
    SendDlgItemMessage(hDlg, IDC_RADIO8, BM_SETCHECK,
    BST_CHECKED, NULL); break;
    }
    Границы выделения памяти
    Граница выделения памяти обуславливаются гранулярностью обращения к памяти через страницы. Так как страница имеет крат- ность 4Кб, то граница выделения любого региона кратна этому зна- чению. Возможные значения определяются граничными значения- ми доступных участков.
    Для отслеживания состояния памяти можно использовать ин- терфейс приложения, приведенного на рисунке 3.3 и приведенный ниже код.
    INT_PTR CALLBACK MemoryInfo(HWND hDlg, UINT message,
    WPARAM wParam, LPARAM lParam)
    {
    UNREFERENCED_PARAMETER(lParam);
    SYSTEM_INFO sys_info
    ;//структура, содержащая
    //
    системную информацию (размер страницы, гранулярность
    // выделения памяти и др.0
    MEMORYSTATUS mem_status = { sizeof(mem_status) }; char buff[256]; string str1="Размер страницы памяти:"; string str2="Байт свободно в страничном файле:"; switch (message)
    { case WM_INITDIALOG:
    SetTimer(hDlg,TIMER,1*500,NULL);
    SendMessage(hDlg, WM_TIMER, NULL, NULL);
    GetSystemInfo(&sys_info); str1=str1+itoa(sys_info.dwPageSize,buff,10)+"\r\n"; sprin tf(buff,"Максимальный адрес доступной памяти:
    %p",sys_info.lpMaximumApplicationAddress); str1=str1+buff+"\r\n";

    25 sprintf(buff,"Минимальный адрес доступной памяти:
    %p",sys_info.lpMinimumApplicationAddress); str1=str1+buff+"\r\n"; sprintf(buff, TEXT("0x%016I64X"), (__int64) sys_info.dwActiveProcessorMask); str1=str1+"Число процессоров:
    "+itoa(sys_info.dwNumberOfProcessors,buff,10)+"\r\n"; str1=str
    1+"Гранулярность резервирования:
    "+buff+"\r\n";
    SetDlgItemText(hDlg,IDC_SYSTEM_INFO,str1.c_str()); return (INT_PTR)TRUE; case WM_TIMER:
    GlobalMemoryStatus(&mem_status
    );//позволяет отслежи- вать текущее состояние памяти sprintf(buff,"%I64d",(__int64) mem_status.dwAvailPageFile); str2=str2+buff+"\r\n"; sprintf(buff,"%d", mem_status.dwTotalPhys); str2=str
    2+"Объем физической памяти в байтах:
    "+buff+"\r\n"; sprintf(buff,"%I64d",(__int64) mem_status.dwAvailPhys); str2=str
    2+"Число байтов свободной физической памяти:
    "+buff+"\r\n"; sprintf(buff,"%I64d",(__int64) mem_status.dwTotalVirtual); str2=str2
    +"Объем виртуальной памяти в байтах):
    "+buff+"\r\n"; sprintf(buff,"%I64d",(__int64) mem_status.dwAvailVirtual); str2=str
    2+"Число байтов свободной виртуальной памяти:
    "+buff+"\r\n"; sprintf(buff,"%I64d",(__int64) mem_status.dwTotalPageFile); str2=str
    2+"Макс. кол-во байт в стран. файле на hdd:
    "+buff+"\r\n"; sprintf(buff,"%d",mem_status.dwMemoryLoad); str2=str
    2+"Насколько занята подсистема управления па- мятью: "+buff+"\r\n";
    SetDlgItemText(hDlg,IDC_MEMORY_STATUS,str2.c_str()); return TRUE;
    } return (INT_PTR)FALSE;

    26
    Рис. 3.3. Информация о распределении памяти
    Регионы в адресном пространстве
    Адресное пространство, выделяемое процессу в момент со- здания, практически все свободно (незарезервировано). Поэтому, чтобы воспользоваться какой-нибудь его частью, нужно выделить в нем определенные регионы через функцию VirtualAlloc.
    Операция выделения региона называется резервированием.
    При резервировании система обязательно выравнивает начало регио- на с учетом так называемой гранулярности выделения памяти. На практике необходимый объем памяти как правило не кратен размеру страницы и программист пытается выделить память не определенно- му количеству страниц, а некому региону памяти.
    Регионом является любая часть памяти внутри адресного пространства потока. Когда зарезервированный регион адресного пространства становится не нужным, его следует вернуть в общие ресурсы системы. Эта операция – освобождение региона – осуществ- ляется вызовом функции VirtualFree.

    27
    Выделение памяти
    Функции для работы с виртуальной памятью манипулируют страницами памяти. Эти функции используют размер страницы на компьютере для округления определенного размера и адреса.
    Функция VirtualAlloc выполняет одну из операций:
    — резервирует определенное количество страниц;
    — передает физическую память зарезервированным страницам;
    — резервирует и передает физическую память страницам.
    Доступ к области, которой передана физическая память, осу- ществляется по обычным ссылкам. case IDC_ALLOC: pMemory1= (char*)GetDlgItemInt(hDlg,IDC_ADRESS,
    &bResult, FALSE); if ( pMemory == NULL )
    { size = GetDlgItemInt(hDlg,IDC_SIZE, &bResult, FALSE); if ( bResult && size>0) pMemory = (char*)VirtualAlloc(
    //возвращает виртуальный адрес региона pMemory1,
    //система должна зарезервировать регион там, где,
    //
    по ее мнению, будет лучше size ,
    //размер резервируемого региона в байтах
    MEM_RESERVE |
    //зарезервировать регион адресного пространства
    MEM_COMMIT
    | //Для передачи физической памяти
    MEM_TOP_DOWN,
    //зарезервировать регион по самым старшим адресам
    PAGE_READWRITE);//указывает атрибут защиты if( pMemory == NULL )
    MessageBox( hDlg, "Нельзя выделить память", "Ошибка",
    MB_ICONERROR); else
    {
    SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING,
    NULL, (LPARAM)"Память выделена");
    VirtualQuery(//заполняет структуру MEMORY_BASIC_INFORMATION
    //информацией о диапазоне смежных страниц, имеющих
    //одинаковые состояние, атрибуты защиты и тип. pMemory,//виртуальный адрес региона
    &memInfo,//адрес структуры MEMORY_BASIC_INFORMATION sizeof(MEMORY_BASIC_INFORMAT
    ION));//размер структуры
    // MEMORY_BASIC_INFORMATION

    28
    На рисунке 3.4 приведен интерфейс программы, демонстрирую- щей работу с виртуальной памятью.
    Рис. 3.4. Работа с виртуальной памятью
    Освобождение памяти
    Функция VirtualFree выполняет одну из операций:
    –– возврат физической памяти;
    –– освобождение региона.
    // освобождение памяти case IDC_FREE_MEMORY: if(pMemory != NULL)
    {
    VirtualFree (pMemory,//базовый адрес региона
    0, // вернет системе весь диапазон выделенных страниц
    MEM_RELEASE);//возврат системе всей физической памяти,
    //отображенной на регион, и освобождение самого региона int count = SendDlgItemMessage(hDlg, IDC_LIST, LB_GETCOUNT,
    NULL, NULL); for (int i = 0; i< count; i++ )
    SendDlgItemMessage(hDlg, IDC_LIST, LB_DELETESTRING, 0, NULL);
    SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING, NULL,
    (LPARAM)"Память не выделена");

    29 pMemory = NULL;
    } else
    MessageBox(hDlg,"Блок памяти не выделен","Ошибка",
    MB_ICONEXCLAMATION); return TRUE;
    Работа со страницами
    Функции VirtualQuery и VirtualQueryEx возвращают информацию об области последовательно расположенных страниц, начиная с опре- деленного адреса в адресном пространстве процесса. VirtualQuery воз- вращает информацию о памяти в текущем процессе.
    VirtualQuery(pMemory,&memInfo,sizeof(MEMORY_BASIC_INFORMATION));
    Изменение атрибутов защиты
    Атрибуты защиты страниц можно поменять функцией
    VirtualProtect.
    // Изменение атрибута защиты case IDC_ATTRIBYTE: if (pMemory == NULL)
    {
    MessageBox(hDlg, "Память не выделена", "Ошибка",
    MB_ICONEXCLAMATION);
    } if( SendDlgItemMessage(hDlg, IDC_RADIO1, BM_GETCHECK, NULL,
    NULL) == BST_CHECKED) dwProtect = PAGE_EXECUTE; if( SendDlgItemMessage(hDlg, IDC_RADIO2, BM_GETCHECK, NULL,
    NULL) == BST_CHECKED) dwProtect = PAGE_EXECUTE_READ; if( SendDlgItemMessage(hDlg, IDC_RADIO3, BM_GETCHECK, NULL,
    NULL) == BST_CHECKED) dwProtect = PAGE_EXECUTE_READWRITE; if( SendDlgItemMessage(hDlg, IDC_RADIO4, BM_GETCHECK, NULL,
    NULL) == BST_CHECKED) dwProtect = PAGE_EXECUTE_WRITECOPY; if( SendDlgItemMessage(hDlg, IDC_RADIO5, BM_GETCHECK, NULL,
    NULL) == BST_CHECKED) dwProtect = PAGE_NOACCESS;

    30 if( SendDlgItemMessage(hDlg, IDC_RADIO6, BM_GETCHECK, NULL,
    NULL) == BST_CHECKED) dwProtect = PAGE_READONLY; if( SendDlgItemMessage(hDlg, IDC_RADIO7, BM_GETCHECK, NULL,
    NULL) == BST_CHECKED) dwProtect = PAGE_READWRITE; if( SendDlgItemMessage(hDlg, IDC_RADIO8, BM_GETCHECK, NULL,
    NULL) == BST_CHECKED) dwProtect = PAGE_WRITECOPY; if( !VirtualProtect( pMemory,// базовый адрес памяти size,//число байтов, для которых изменяете атрибут защиты dwProtect, //новый атрибут защиты
    &dwOldProtect))//адрес переменной типа DWORD,
    //в которую VirtualProtect заносит
    //
    старое значение атрибута защиты
    MessageBox( hDlg, "Не удалось изменить атрибуты защиты",
    "Ошибка", MB_OK); break;
    1   2   3   4   5   6


    написать администратору сайта