Є дві основні причини.
Перша причина полягає в тому, що, хоча процесори x86 мають чотири кільця захисту пам’яті, деталізація захисту, що пропонується, є лише на рівні сегмента. Тобто кожен сегмент може бути встановлений на певне кільце ("рівень привілеїв") від 0 до 3 разом з іншими захистами, такими як відключення запису. Але доступно не так багато дескрипторів сегмента. Більшість операційних систем хотіли б мати значно тоншу деталізацію захисту пам'яті. Як ... для окремих сторінок.
Отже, введіть захист на основі записів таблиці сторінок (PTE). Більшість, якщо не всі сучасні операційні системи x86, більш-менш ігнорують механізм сегментації (все одно наскільки це можливо) і покладаються на захист на основі PTE. Це визначено бітами прапорців, які є нижчими 12 бітами в кожному PTE - плюс біт 63 на процесорах, які підтримують виконання без виконання. Для кожної сторінки є один PTE, який зазвичай становить 4K.
Один з цих бітів прапора називається "привілейованим" бітом. Цей біт контролює, чи повинен процесор знаходитись на одному з "привілейованих" рівнів для доступу до сторінки. "Привілейовані" рівні - PL 0, 1 і 2. Але це лише один біт, тому на рівні захисту сторінок за сторінкою кількість "режимів", що стосується захисту пам'яті, становить всього два: Сторінка може бути доступним у непривілейованому режимі, чи ні. Звідси всього два кільця.
Щоб мати чотири можливі кільця для кожної сторінки, вони повинні мати два біти захисту у кожній записи таблиці сторінок, щоб кодувати один з чотирьох можливих номерів кільця (так само, як це роблять дескриптори сегмента). Вони ні.
Друга причина - мета переносимості ОС. Справа не лише в x86; Unix навчив нас, що ОС може бути відносно портативною для декількох архітектур процесорів, і що це було гарною справою. А деякі процесори підтримують лише два кільця. Не залежно від кількох кілець в архітектурі, реалізатори ОС зробили ОС більш портативною.
Є третя причина, яка характерна для розробки Windows NT. Дизайнери NT (Девід Катлер та його команда, яких Microsoft найняв у лабораторії західної області DEC) мали великий попередній досвід роботи з VMS; насправді Катлер та деякі інші були одними з оригінальних дизайнерів VMS. А VAX-процесор, для якого VMS був розроблений (і навпаки), має чотири кільця. VMS використовує чотири кільця. (Насправді VAX має чотири біти захисту в PTE, завдяки чому можливі комбінації, такі як "тільки для читання з користувальницького режиму, але для запису з кільця 2 і внутрішнього". Але я відволікаюсь.)
Але компоненти, які працювали в кільцях 1 та 2 VMS (Служби управління записом та CLI, відповідно), залишилися поза конструкцією NT. Ring 2 у VMS насправді стосувався не безпеки ОС, а, зокрема, збереження середовища CLI користувача від однієї програми до іншої, і Windows NT просто не мав такої концепції; CLI працює як звичайний процес. Що стосується кільця 1 VMS, код RMS у кільці 1 доводиться закликати в кільце 0 досить часто, а переходи кільця дорогі. Набагато ефективніше виявилося просто перейти до дзвінка 0 та зробити це з ним, а не мати багато переходів кільця 0 у коду 1. (Знову ж таки - не те, що у NT все одно є щось на зразок RMS.)
Але чому вони тоді там? Що стосується того, чому x86 реалізував чотири кільця, поки ОС не використовували їх - ви говорите про ОС набагато новішого дизайну, ніж x86. Багато функцій «системного програмування» x86 було розроблено задовго до того, як на ньому були впроваджені NT або справжні ядра Unix-ish, і вони не знали, що саме використовуватимуть ОС. (Тільки до того, як ми не отримали підкачки на x86 - який не з'явився до 80386 року) - ми могли реалізувати справжні ядра Unix або VMS, не переосмислюючи управління пам'яттю з нуля.)
Не тільки сучасні ОС x86 в основному ігнорують сегментацію (вони просто встановлюють сегменти C, D і S з базовою адресою 0 і розміром 4 ГБ; сегменти F і G іноді використовуються для вказівки на ключові структури даних ОС), вони також значною мірою ігнорують такі речі, як "сегменти стану завдань". Механізм TSS був чітко розроблений для переключення контексту потоку, але виявляється, що він має занадто багато побічних ефектів, тому сучасні ОС x86 роблять це "вручну". Єдиний раз, коли x86 NT змінює апаратні завдання, наприклад, для деяких справді виняткових умов, як виняток подвійної помилки.
Зрештою, 64 багато з цих використаних функцій були залишені. (На їхню честь, AMD насправді поспілкувався з командами ядра ОС і запитав, що їм потрібно від x86, що їм не потрібно чи не хочеться, і що вони хотіли б додати.) Сегменти на x64 існують лише у тому, що може бути називається вестигіальною формою, перемикання стану задач не існує і т. д. А ОС продовжують використовувати лише два кільця.