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

:: Меню ::

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

:: Друзі ::

Карта сайту
 

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

 

 

 

 

 

Взаємно недовіряючі підсистеми

  — Ви куди?
— У мене там портфель!
— Я вам його принесу!
— Я вам не довіряю. У мене там коштовний віник. ("Іронія долі або з легкою парою!")
Г. Горін

З точки зору безпеки, основною проблемою систем з кільцями захисту є нездатність таких систем захистити себе від помилок в модулях, що виконуються у вищому кільці захисту. В світлі цього, дуже привабливою концепцією представляється ідея взаємно недовіряючих підсистем.
Згідно цієї концепції, призначене для користувача завдання не повинне надавати системі доступу до всіх своїх даних. Замість цього завдання повинне видавати мандат на доступ до буфера або декількох буферів, призначених для обміну даними. Всі акти обміну даними як між призначеним для користувача завданням і системою, так і між двома призначеними для користувача завданнями або двома модулями системи, також здійснюються за допомогою передачі мандатів.
Наприклад, при виконання системного виклику int read (int file, void * buf, size_t size) програма повинна передати системі мандат на право запису в буфер buf розміром size байт (мал. 5.11). При цьому буфер відображуватиме в адресний простір підсистеми ввода/вивода, але ця підсистема не отримає права запису в останній адресний простір нашого завдання. Втім, цей підхід має дві очевидні проблеми.

Мал. 5.11. Передача мандатів

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

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

  • Переконатися в тому, що передаваний об'єкт цілком входить в один сегмент вихідного адресного простору.
  • Якщо об'єкт складається з декількох сегментів, розумним чином обробити таку ситуацію. Для програмної реалізації може виявитися бажаним уміння об'єднати всі елементи в один сегмент. Для апаратної або мікропрограмної реалізації досить хоч би уміти згенерувати відповідне виключення.
  • Сформувати вміст дескриптора сегменту для об'єкту і записати в нього відповідні права. Ця операція вимагає заповнення 4—5 бітових полів, і запис її алгоритму на псевдокоді займе близько десятка операторів. По складності алгоритму одна лише ця операція порівнянна з найбільш складними командами сучасних комерційних CISC-процессоров, таких як VAX або трансп'ютер.
  • Відзначити в загальносистемній базі даних, що на відповідну область фізичної пам'яті існує два заслання. Це потрібно для того, щоб процеси дефрагментації і управління віртуатьной пам'яттю правильно обробляли переміщення сегменту по пам'яті і його перенесення на диск, відзначаючи зміни фізичної адреси або ознаки присутності у всіх дескрипторах, що посилаються на даний сегмент. Далі ця проблема обговорюватиметься детальніше.
  • Знайти вільний запис в таблиці дескрипторів сегментів завдання-одержувача. Ця операція аналогічна строковим командам CISC-процессоров, які вважаються складними командами.
  • Розумним чином обробити ситуацію відсутності такого запису.
  • Записати сформований дескриптор в таблицю.

Але еше більше проблем створює операція знищення мандата. Легко показати необхідність знищення мандата тим же завданням, яке його створила.

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

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

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

Остання вимога безпосередньо не виходить з концепції взаємно недовіряючих підсистем, але диктується простим здоровим глуздом. Якщо ми і змиримося з двух- або кратнішим збільшенням потреб в пам'яті, виправдовуючи його підвищенням надійності, не можна забувати, що навіть простий перегляд таблиць багатомегабайтів не може бути швидким.
У системах, що використовують сторінкові диспетчери пам'яті, вирішити ці Проблеми набагато простіше, бо мінімальним квантом розділення Пам'яті є сторінка розміром декілька кілобайт. Завдяки цьому Ми сміливо можемо пов'язати з кожним квантом, що розділяється, декілька десятків байтів даних, що забезпечують виконання перших двох вимог.
Якщо ж мінімальним квантом є байт або слово пам'яті, наші структури даних опиняться у багато разів більше розподілюваної пам'яті.
Автор залишає читачеві можливість спробувати самостійно розробити відповідну структуру даних. Як складніша вправа можна рекомендувати записати алгоритм роботи з такою базою даних на псевдокоді, враховуючи, що ми хотіли б мати можливість реалізувати цей алгоритм апаратний або, принаймні, мікропрограмний.
Додатковою стимул-реакцією для читача, що вирішив взятися за це завдання, може служити той факт, що розробники фірми Intel не змогли знайти задовільного рішення.

Архітектура 1432
Авторові відомий лише один процесор, придатний для повноцінної реалізації взаємно недовіряючих підсистем: Japx432 фірми Intel. Замість створення системної бази даних про множинні заслання на об'єкти, фахівці фірми Intel ускладнили диспетчер пам'яті і відповідно алгоритм дозволу віртуальних адрес.
Віртуальна адреса в 1432 складається з селектора об'єкту і зсуву в цьому об'єкті. Селектор об'єкту посилається на таблицю доступу поточного домена. Доменом є програмний модуль разом зі всіма його статичними і динамічними даними (мал. 5.12). По ідеї розробників, домен відповідає замкнутому модулю мов високого рівня, наприклад пакету (package) мови Ada.

Мал. 5.12. Домен 1432

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

segment_table[seg].phys_address + offset


ми маємо

object_table[access_table[selector]].phys_address + offset.

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

Мал. 5.13. Уточнення

Цільовий об'єкт також може виявитися уточненням, і диспетчер пам'яті повторюватиме процедуру до тих пір, поки не дійде до об'єкту, що посилається на фізичну пам'ять. Детальніше цей механізм описаний в роботі [Органік 1987].
Уточнення дозволяють вирішити проблему видачі мандатов— мандат реалізується як уточнення вихідного об'єкту (наприклад, сегменту даних модуля в якому виділений буфер), а програмі-одержувачеві передається навіть не само уточнення, а лише дескриптор доступу до нього. Для припинення дії мандата досить видалити дескриптор уточнення. Після цього всі передані іншим модулям дескриптори доступу вказуватимуть в порожнечу, тобто стануть недійсними. Завдання ж переміщення в пам'яті і скидання об'єктів на диск вирішуються шляхом зміни фізичної адреси або ознаки п(в|рутствія цільового об'єкту; для цього не потрібно просліджувати ланцюжок уточнень.
Проте накладні витрати, пов'язані з реалізацією цього складного механізму, виявилися дуже великими. Процесор i432 залишився експериментальним і не отримав практичного вживання. Важко сказати, який з чинників виявився важливішим: катастрофічно низька продуктивність системи (авторові не удалося знайти офіційних заяв фірми Intel із цього приводу, але народна мудрість стверджує, що експериментальні зразки i432 з тактовою частотою 20 Мгц виконували близько 20 000 операцій в секунду) або просто нездатність фірми Intel довести надмірно складний кристал до масового промислового виробництва. Так або інакше, чи не єдиною практичною користю, що витягує з цього амбітного проекту, виявилося тестування системи автоматизованого проектування, використаної згодом при розробці процесора 80386 і супутніх мікросхем.
Після завершення проекту I432 інших спроб повністю реалізувати взаємно недовіряючі підсистеми не робилося — виготівники комерційних систем, мабуть, визнали цю ідею непродуктивною, а дослідницьким організаціям проекти такого масштабу просто не по плечу.

 

:: Реклама ::

 

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


 

 

 


Copyright © Kivik, 2017