Теорія операційної системи

:: Меню ::

Головна
Представлення даних в обчислювальних системах
Машинні мови
Завантаження програм
Управління оперативною пам'яттю
Сегментна і сторінкова віртуальна пам'ять
Комп'ютер і зовнішні події
Паралелізм з точки зору програміста
Реалізація багатозадачності на однопроцесорних комп'ютерах  
Зовнішні пристрої
Драйвери зовнішніх пристроїв
Файлові системи
Безпека
Огляд архітектури сучасних ОС

:: Друзі ::

Карта сайту
 

:: Статистика ::

 

 

 

 

 

Відкрита пам'ять (продовження)

Описані вище алгоритми розподілу пам'яті використовуються не операційною системою, а бібліотечними функціями, приєднаними до програми. Проте ОС, яка реалізує одночасне завантаження (але не обов'язкове одночасного виконання: MS DOS — типовий приклад такої системи) декількох завдань, також повинна використовувати той або інший алгоритм розміщення пам'яті. Частково такі алгоритми можуть бути схожі на роботу функції malloc. Проте режим роботи ОС може вносити істотні спрощення до алгоритму.
Переміщати образ завантаженого процесу по пам'яті неможливо: навіть якщо його код був позіционно-незавісим і не піддавався перенастроюванню, сегмент даних може містити (і майже напевно містить) покажчики, які при переміщенні необхідно перенастроювати. Тому при вивантаженні завдань з пам'яті перед нами в повне зростання встає проблема зовнішньої фрагментації (мал. 4.13).

Мал. 4.13. Фрагментація при завантаженні і вивантаженні завдань

Управління пам'яттю в Os/360
В зв'язку з цим не можна не згадати про повчальну історію, пов'язану з управлінням пам'яттю в системах лінії IBM System 360. У цих машинах не було апаратних засобів управління пам'яттю, і всі програми розділяли спільний віртуальний адресний простір, співпадаючий з фізичним. Адресні заслання в програмі задавалися 12-бітовим зсувом відносно базового регістра. Як базовий регістр міг використовуватися, в принципі, будь-який з 16 32-бітових регістрів спільного призначення. Передбачалося, що призначені для користувача програми не модифікують базовий регістр, тому можна завантажувати їх з різних адрес, просто перенастроюючи значення цього регістра. Таким чином, було реалізовано одночасне завантаження багато про" грам в багатозадачній системі Os/360.
Проте після завантаження програму вже не можна було переміщати по пам'яті: наприклад, при виклику підпрограми адреса повернення зберігається у вигляді абсолютної 24-бітовог.о адреси (у System 360 під адресу відводилося 32-розрядне слово, але використовувалися лише 24 молодших біта адреси. У System 370 адреса стала 31-розрядним) і при поверненні базовий регістр не застосовується. Аналогічно, базовий регістр не використовується при засланнях на блоки параметрів і самі параметри підпрограм мови FORTRAN (у цій мові всі параметри передаються по засланню), при роботі з покажчиками в Pl/i і так далі Переміщення програми, навіть з перенастроюванням базового регістра, порушило б всі такі заслання.
Розробники фірми IBM незабаром усвідомили користь переміщення програм після їх завантаження і спробували якось вирішити цю проблему. Дуже цікавий документ "Preparing to Rollin-rollout Guideline" (Керівництво по підготовці [програми] до укочування і викочування; на жаль, авторові не удалося знайти повного тексту цього документа) описує дії, які програма повинна була б зробити після переміщення. Фактично програма повинна була знайти в своєму сегменті даних всі абсолютні адреси і сама перенастроювати їх.
Природно, ніхто з розробників компіляторів і прикладного програмного забезпечення не збирався слідувати цьому керівництву. В результаті, проблема переміщення програм в Os/360 не була вирішена аж до появи машин System 370 із сторінковим або сторінково-сегментним диспетчером пам'яті і ОС MVS.

В даному випадку проблема фрагментації особливо гостра, оскільки типовий образ процесу займає значну частину всього доступного ОЗУ. Якщо при виділенні невеликих блоків ми ще можемо розраховувати на "закон великих чисел" і інші статистичні закономірності, то найпростіший сценарій завантаження трьох процесів різного розміру може привести нас до нерозв'язної ситуації (див. мал. 4.13).
Розділи пам'яті (див. разд. Розділи пам'яті) частково дозволяють вирішити проблему зовнішньої фрагментації, встановлюючи, що процес повинен або використовувати розділ Цілком, або не використовувати його зовсім. Як і всі обмеження на розмір одиниці виділення пам'яті, це рішення заганяє проблему всередину, переводячи зовнішню фрагментацію у внутрішню. Тому деякі системи пропонують інші способи накладення обмеження на порядок завантаження і вивантаження завдань.

Управління пам'яттю в MS DOS
Так, наприклад, процедура управління пам'яттю MS DOS розрахована на випадок, коли програми вивантажуються з пам'яті лише в порядку, зворотному тому, в якому вони туди завантажувалися (на практиці, вони можуть вивантажуватися і в іншому порядку, але це явно заборонено в документації і часто приводить до проблем). Це дозволяє звести управління пам'яттю до стекової дисципліни.
Кожній програмі в MS DOS відводиться блок пам'яті. З кожним таким блоком асоційований дескриптор, званий МСВ — Memory Control Block (мал. 4.14). Цей дескриптор містить розмір блоку, ідентифікатор програми, якою належить цей блок, і ознака того, чи є даний блок
останнім в ланцюжку. Потрібно відзначити, що програмі завжди належить декілька блоків, але це вже неістотні деталі. Інша малоістотна деталь та, що розмір сегментів і їх адреси відлічуються в параграфах розміром 16 байт. Знайомі з архітектурою процесора 8086 повинні пригадати, що адреса МСВ в цьому випадку складатиметься лише з сегментної частини з нульовим зсувом.
Після запуску corn-файл отримує сегмент розміром 64кбайт, а ехе — всю доступну пам'ять. Зазвичай ехе-модули відразу після запуску визволяють непотрібну ним пам'ять і встановлюють brklevel на кінець свого сегменту, а потім збільшують brklevel і нарощують сегмент в міру необхідності.
Природно, що нарощувати сегмент можна лише за рахунок наступного за ним в ланцюжку МСВ, і MS DOS дозволить робити це лише у випадку, якщо цей сегмент не належить жодній програмі.
При запуску програми DOS бере останній сегмент в ланцюжку і завантажує туди програму, якщо цей сегмент досить великий. Якщо він недостатньо великий, DOS говорить: "Недостатньо пам'яті" і відмовляється завантажувати програму. При завершенні програми DOS визволяє всі блоки, що належали програмі. При цьому сусідні блоки об'єднуються. Поки програми, дійсно, завершуються в порядку, зворотному тому, в якому вони запускалися, — все цілком нормально. Інша справа, що в реальному житті можливі відхилення від цієї схеми. Наприклад, передбачається, що TSR-программы (Terminate, but Stay Resident - Завершитися і залишитися резидентний (у пам'яті)) ніколи не намагаються по-справжньому завершитися і вивантажитися. Проте, будь-який хакер, що поважає себе, вважає своїм обов'язком зробити резидентну програму вивантажуваної. У деяких хакерів вона в результаті викидає при вивантаженні всі резиденти, які зайняли пам'ять після неї. Інший приклад — відладчики зазвичай завантажують програму в обхід звичайної Dos-овськой функції LOAD & EXECUTE, а при завершенні відладжуваної програми самі визволяють займану нею пам'ять.
Автор свого часу займався проходженням деякої програми під управлінням відладчика. Чесно кажучи, йшлося про злом деякої іграшки... Ця програма проводила якусь ініціалізацію, а потім викликала функцію DOS LOAD & EXECUTE. Я про це не знав і, природно, попав всередину нової програми, яку і повинен був зламувати.
Після декількох натиснень комбінацій клавіш <Ctrl>+<break> я нарешті повернувся у відладчик, але при якомусь дуже дивному достатку програми. Попорпавшись в програмі за допомогою відладчика протягом деякого часу і переконавшись, що вона не хоче приходити в нормальний достаток, я вийшов з відладчика і побачив наступну картину: системі доступний близько 100 Кбайт в той час, як сума довжин вільних блоків пам'яті більше 300 Кбайт, а розмір найбільшого вільного блоку близько 200 Кбайт. Відладчик виходячи, визволив свою пам'ять і пам'ять відладжуваної програми, але не визволив пам'ять, виділену новому завантаженому модулю. В результаті посередині пам'яті ос-тался нікому не потрібний блок неабиякого розміру, помічений як використовуваний (мал. 4.15). Найобразливішим було те, що DOS не намагалася завантажити жодну програму в пам'ять під цим блоком, хоча там було значно більше місця, чим над ним.

Мал. 4.14. Управління пам'яттю в MS DOS

Мал. 4.15. Порушення стекового порядку завантаження і вивантаження в MS DOS

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

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

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

 

:: Реклама ::

 

:: Посилання ::


 

 

 


Copyright © Kivik, 2017