6.8: Підтримка обладнання
- Page ID
- 34537
Поки ми лише згадували, що апаратне забезпечення працює з операційною системою для реалізації віртуальної пам'яті. Однак ми проглянули деталі того, як саме це відбувається.
Віртуальна пам'ять обов'язково досить залежить від апаратної архітектури, і кожна архітектура має свої тонкощі. Однак є кілька універсальних елементів віртуальної пам'яті в апаратному забезпеченні.
Всі процесори мають певну концепцію або роботи в фізичному, або віртуальному режимі. У фізичному режимі апаратне забезпечення очікує, що будь-яка адреса буде посилатися на адресу в реальній системній пам'яті. У віртуальному режимі апаратне забезпечення знає, що адреси потрібно буде перекласти, щоб знайти їх фізичну адресу.
У багатьох процесорах ці два режими просто іменуються фізичним і віртуальним режимами. Одним з таких прикладів є Itanium. Найпоширеніший процесор, x86, має багато багажу за кілька днів до віртуальної пам'яті, і тому два режими називаються реальним і захищеним режимом. Першим процесором, який реалізував захищений режим, став 386, і навіть найсучасніші процесори в лінійці сімейства x86 все ще можуть робити реальний режим, хоча він і не використовується. У реальному режимі процесор реалізує форму організації пам'яті, яка називається сегментацією.
Сегментація дійсно цікава лише як історична замітка, оскільки віртуальна пам'ять зробила її менш актуальною. Сегментація має ряд недоліків, не в останню чергу з яких вона дуже заплутана для недосвідчених програмістів, які системи віртуальної пам'яті були багато в чому придумані для обійти.
У сегментації існує ряд регістрів, які містять адресу, яка є початком сегмента. Єдиний спосіб дістатися до адреси в пам'яті - вказати його як зсув від одного з цих регістрів сегментів. Розмір відрізка (а отже, і максимальне зміщення, яке ви можете вказати) визначається кількістю бітів, доступних для зсуву від базового регістра сегмента. У x86 максимальне зміщення становить 16 біт, або тільки 64K [18]. Це викликає всілякі хаос, якщо хочеться використовувати адресу, яка знаходиться на відстані більше 64 Кб, який у міру зростання пам'яті в мегабайти (а тепер і гігабайти) став більш ніж невеликою незручністю для повного збою.
На наведеному вище малюнку є три сегментні регістри, які всі вказують на сегменти. Максимальне зміщення (обмежене кількістю доступних бітів) відображається затіненням. Якщо програма хоче отримати адресу поза цим діапазоном, регістри сегментів повинні бути переналаштовані. Це швидко стає головним роздратуванням. Віртуальна пам'ять, з іншого боку, дозволяє програмі вказати будь-яку адресу, а операційна система та обладнання виконують важку роботу з перекладу на фізичну адресу.
Буфер перекладу Lookaside (або коротко TLB) є основним компонентом процесора, що відповідає за віртуальну пам'ять. Це кеш віртуальної сторінки до фізико-кадрів перекладів всередині процесора. Операційна система та апаратне забезпечення працюють разом, щоб керувати TLB під час роботи системи.
Коли віртуальну адресу запитують апаратне забезпечення - скажімо, через інструкцію завантаження, яка вимагає отримати деякі дані - процесор шукає віртуальну адресу для перекладу фізичної адреси у своєму TLB. Якщо він має дійсний переклад, він може об'єднати це зі зміщеною частиною, щоб перейти безпосередньо до фізичної адреси та завершити завантаження.
Однак якщо процесор не може знайти переклад в TLB, процесор повинен підняти сторінку несправності. Це схоже на переривання (як обговорювалося раніше), яке операційна система повинна обробляти.
Коли операційна система отримує помилку сторінки, їй потрібно пройти її сторінку-таблицю, щоб знайти правильний переклад і вставити його в TLB.
У разі, якщо операційна система не може знайти переклад в таблиці сторінок, або, як варіант, якщо операційна система перевіряє дозволи відповідної сторінки і процес не має права доступу до неї, операційна система повинна вбити процес. Якщо ви коли-небудь бачили помилку сегментації (або segfault), це операційна система вбиває процес, який переступив свої межі.
Якщо переклад буде знайдено, а TLB наразі буде повним, то один переклад потрібно вилучити, перш ніж можна буде вставити інший. Не має сенсу видаляти переклад, який, ймовірно, буде використаний в майбутньому, оскільки ви будете нести витрати на пошук запису в таблицях сторінок знову. TLB зазвичай використовують щось на кшталт алгоритму «Найменш недавно використаний» або «LRU», де найстаріший переклад, який не використовувався, викидається на користь нового.
Потім доступ можна спробувати ще раз, і, все йде добре, слід знайти в TLB і правильно перекласти.
Коли ми говоримо, що операційна система знаходить переклад в таблиці сторінок, логічно запитати, як операційна система знаходить пам'ять, яка має таблицю сторінок.
База таблиці сторінок буде зберігатися в реєстрі, пов'язаному з кожним процесом. Зазвичай це називається сторінка-таблиця base-register або подібним. Взявши адресу в цьому реєстрі і додавши до нього номер сторінки, можна розташувати правильний запис.
Є ще дві важливі помилки, які TLB зазвичай може генерувати, які допомагають керувати доступними та брудними сторінками. Кожна сторінка, як правило, містить атрибут у вигляді одного біта, який позначає, якщо сторінка була доступна або є брудною.
Доступ до сторінки - це просто будь-яка сторінка, до якої було отримано доступ. Коли переклад сторінки спочатку завантажується в TLB, сторінка може бути позначена як була доступна (інакше чому ви завантажували її в? [19])
Операційна система може періодично переглядати всі сторінки і очищати доступ біт, щоб отримати уявлення про те, які сторінки в даний час використовуються. Коли системна пам'ять стає повною, і настає час для операційної системи вибирати сторінки, які будуть замінені на диск, очевидно, ті сторінки, доступ до яких біт не був скинутий, є найкращими кандидатами на видалення, оскільки вони не використовувалися найдовше.
Брудна сторінка - це та, яка має дані, записані на неї, і тому не збігається з будь-якими даними, які вже є на диску. Наприклад, якщо сторінка завантажується з підкачки, а потім записується процесом, перш ніж вона може бути переміщена з підкачки, вона повинна мати його на диску копію оновлено. Сторінка, яка є чистою, не мала змін, тому нам не потрібні накладні витрати на копіювання сторінки назад на диск.
Обидва схожі тим, що допомагають операційній системі керувати сторінками. Загальна концепція полягає в тому, що сторінка має два зайвих біти; брудний біт і доступ біт. Коли сторінка поміщена в TLB, ці біти встановлюються так, щоб вказувати на те, що процесор повинен викликати несправність.
Коли процес намагається посилатися на пам'ять, апаратне забезпечення виконує звичайний процес перекладу. Однак він також робить додаткову перевірку, щоб побачити, чи не встановлено прапорець доступу. Якщо це так, то це викликає несправність операційної системи, яка повинна встановити розрядність і дозволити процес продовжити. Аналогічно, якщо апаратне забезпечення виявить, що воно пише на сторінку, на якій не встановлено брудний біт, це викличе помилку для операційної системи позначити сторінку як брудну.
Можна сказати, що TLB використовується апаратним забезпеченням, але управляється програмним забезпеченням. Операційна система повинна завантажити TLB з правильними записами і видалити старі записи.
Процес видалення записів з TLB називається промиванням. Оновлення TLB є вирішальною частиною підтримки окремих адресних просторів для процесів; оскільки кожен процес може використовувати ту саму віртуальну адресу, не оновлюючи TLB, означатиме, що процес може закінчитися перезаписом пам'яті інших процесів (навпаки, у випадку потоків спільного використання адресного простору) це те, що ви хочете, таким чином TLB не змивається при перемиканні між потоками в одному і тому ж процесі).
На деяких процесорах кожен раз, коли є перемикач контексту, весь TLB змивається. Це може бути досить дорогим, оскільки це означає, що новий процес доведеться пройти весь процес прийняття несправності сторінки, пошуку сторінки в таблицях сторінок і вставки перекладу.
Інші процесори реалізують додатковий ідентифікатор адресного простору (ASID), який додається до кожного перекладу TLB, щоб зробити його унікальним. Це означає, що кожен адресний простір (зазвичай кожен процес, але пам'ятайте, що потоки хочуть поділитися тим же адресним простором) отримує свій власний ідентифікатор, який зберігається разом з будь-якими перекладами в TLB. Таким чином, на контекстному перемиканні TLB не потрібно промивати, оскільки наступний процес матиме інший ідентифікатор адресного простору, і навіть якщо він запитує той же віртуальний адресу, ідентифікатор адресного простору буде відрізнятися, і тому переклад на фізичну сторінку буде відрізнятися. Ця схема зменшує промивання та збільшує загальну продуктивність системи, але вимагає більше апаратного забезпечення TLB для утримання бітів ASID.
Як правило, це реалізується шляхом наявності додаткового реєстру як частини стану процесу, який включає ASID. Під час виконання віртуально-фізичного перекладу TLB звертається до цього реєстру і буде відповідати лише тим записам, які мають той самий ASID, що і поточний запущений процес. Звичайно, ширина цього регістру визначає кількість доступних ASID і, таким чином, має наслідки для продуктивності. Приклад ASID в архітектурі процесора див. розділ під назвою «Адресні простори».
Хоча контроль того, що закінчується в TLB, є доменом операційної системи; це не вся історія. Процес, описаний у розділі «Помилка сторінки», описує помилку сторінки, яка піднімається в операційній системі, яка проходить таблицю сторінок, щоб знайти віртуально-фізичний переклад і встановлює його в TLB. Це буде називатися програмним завантаженням TLB - але є й інша альтернатива; апаратно завантажений TLB.
У апаратному завантаженому TLB архітектура процесора визначає певний макет інформації про таблицю сторінок (розділ під назвою «Сторінки+кадри = Таблиці сторінок», який слід дотримуватися, щоб продовжити трансляцію віртуальної адреси. У відповідь на доступ до віртуальної адреси, якого немає в TLB, процесор автоматично буде ходити по таблицях сторінок, щоб завантажити правильний запис перекладу. Тільки якщо запис перекладу не існує, процесор викличе виняток, який обробляється операційною системою.
Реалізація обходу таблиці сторінок у спеціалізованому обладнанні дає переваги швидкості при пошуку перекладів, але усуває гнучкість з боку реалізаторів операційних систем, які можуть захотіти реалізувати альтернативні схеми для столів сторінок.
Усі архітектури можуть бути широко класифіковані на ці дві методології. Пізніше ми розглянемо деякі поширені архітектури та їх підтримку віртуальної пам'яті.
[18] Уявіть, що максимальне зміщення становило 32 біти; у цьому випадку весь адресний простір можна отримати як зсув від сегмента в 0x00000000, і ви, по суті, мали б плоский макет - але це все ще не так добре, як віртуальна пам'ять, як ви побачите. Насправді єдина причина, по якій це 16 біт, полягає в тому, що оригінальні процесори Intel були обмежені цим, а чіпи підтримують зворотну сумісність.
[19] Насправді, якби ви завантажували його без очікуваного доступу, це називалося б спекуляцією, де ви щось робите з очікуванням, що це окупиться. Наприклад, якщо код читав по пам'яті лінійно, введення наступного перекладу сторінки в TLB може заощадити час і підвищити продуктивність.