Регіони

Розглянемо тепер, яким чином програма процесу може використовувати свій адресний простір.

Спроба просто-напросто використовувати в програмі довільно вибрану адресу в межах адресного простору процесу, швидше за все, призведе до видачі повідомлення про помилку захисту пам'яті. Насправді, використовувати віртуальну адресу можна тільки після того, як йому поставлений у відповідність адресу фізичний. Таке зіставлення виконується шляхом виділення регіонів віртуальної пам'яті.

Регіон пам'яті завжди має розміри, кратні 4 Кб (тобто він містить ціле число сторінок), а його початкова адреса кратний 64 Кб.

Для виділення регіону використовується функція VirtualAlloc. Вона вимагає вказівки наступних параметрів.

· Початковий віртуальний адреса регіону. Якщо вказана константа NULL, то система сама вибирає адресу. Якщо вказана адреса, не кратний 64 К, то система округляє його вниз.

· Розмір регіону. При необхідності система округляє його до величини, кратної 4 Кб.

· Тип виділення. Тут вказується одна з констант MEM_RESERVE (резервування пам'яті) або MEM_COMMIT (передача фізичної пам'яті), зміст яких буде детально розглянуто нижче, або комбінація обох констант.

· Тип доступу. Він визначає, які операції можуть виконуватися зі сторінками виділеної пам'яті. Найбільш важливі наступні типи доступу.

- PAGE_READONLY - доступ тільки для читання, спроба запису в пам'ять призводить до помилки.

- PAGE_READWRITE - доступ для читання і запису.

- PAGE_GUARD - додатковий прапор «охорони сторінок», який повинен комбінуватися з одним із попередніх. При першій же спробі доступу до охоронюваної сторінці генерується переривання, який сповіщає про це систему. При цьому прапор охорони автоматично знімається, так що подальша робота зі сторінкою виконується без проблем.

Найважливіше, що слід зрозуміти про виділення регіонів, це сенс операцій резервування та передачі пам'яті.

Резервування регіону пам'яті (MEM_RESERVE) означає всього лише те, що діапазон віртуальних адрес, відповідних даному регіону, не буде використаний під жодні інші цілі, система вважає його зайнятим. Це як резервування авіаквитка: ви поки що не володієте квитком, але і нікому іншому його не продадуть.

Спроба програми звернутися до адресою в зарезервованому, але не переданій регіоні призведе до помилки.

Передача фізичної пам'яті (MEM_COMMIT) означає, що за кожною сторінкою віртуальної пам'яті регіону система закріплює ... ні, зовсім не сторінку фізичної пам'яті, як можна подумати. Закріплюється блок розміром 4 Кб в сторінковому файлі. У таблиці сторінок процесу передані сторінки позначаються як відсутні в пам'яті.

Тепер спроба звернення до адресою в регіоні призведе вже до зовсім іншого результату. Оскільки сторінка відсутня в пам'яті, відбудеться переривання. Однак це не буде розглядатися як помилка в програмі. Система, обробляючи переривання, виконає операцію читання сторінки з диска, з сторінкового файлу, в основну пам'ять і занесе в таблицю сторінок фізичну адресу, який тепер відповідає віртуальній сторінці. Після цього команда, що викликала переривання, буде повторена, але тепер вже з успіхом, оскільки потрібна сторінка знаходиться в пам'яті. Подальші звернення до тієї ж віртуальної сторінці будуть виконуватися без проблем, поки сторінка знаходиться в пам'яті.

Резервування та передача пам'яті можуть виконуватися одночасно, при одному зверненні до функції VirtualAlloc, якій для цього потрібно передати комбінацію обох констант: MEM_RESERVE + MEM_COMMIT. Є й інший варіант: спочатку зарезервувати регіон пам'яті, а потім, у міру необхідності, передавати фізичну пам'ять або всьому регіону відразу, або його окремим частинам (субрегіону). Для цього в перший раз функція VirtualAlloc викликається з константою MEM_RESERVE і, як правило, без зазначення конкретної адреси. Потім викликається VirtualAlloc з константою MEM_COMMIT і з зазначенням адреси раніше зарезервованого регіону або відповідного субрегіону.

Все описане повністю відповідає поняттю завантаження сторінок по вимозі, описаному в п. 5.5. В якості особливостей реалізації заміщення сторінок в Windows слід зазначити наступне.

· Для кожного процесу в системі визначені максимальний і мінімальний розмір його робочого безлічі. При виборі витісняється сторінки система намагається домогтися, щоб за кожним процесом зберігалося не менше мінімального, але не більше максимальної кількості пам'яті. Це дозволяє уникнути ситуації, коли один процес, марнотратно використовує пам'ять, витісняє з неї майже всі сторінки інших процесів. Процес може змінити розміри свого робочого безлічі, але при цьому сумарні вимоги всіх процесів обмежуються реальним розміром наявної пам'яті.

· Процес може замкнути в пам'яті деякий діапазон адрес, щоб перешкодити витіснення відповідних сторінок на диск. Сумарний розмір пам'яті, замкненої одним процесом, за замовчуванням не повинен перевершувати 30 сторінок. Тривале утримання одним процесом великої кількості сторінок замкнутими в пам'яті призвело б до зменшення обсягу пам'яті, доступного для інших процесів (та й для незамкнених сторінок того ж процесу).