Як працює підкачка x86?


91

Це питання покликане заповнити вакуум доброї безкоштовної інформації з цього питання.

Я вважаю, що хороша відповідь впишеться в одну велику ТАК відповідь або, принаймні, у кілька відповідей.

Основна мета - надати початківцям початківцям достатньо інформації, щоб вони могли самостійно взяти посібник та зрозуміти основні концепції ОС, пов’язані з підкачкою.

Рекомендовані вказівки:

  • відповіді повинні бути зручними для початківців:
    • конкретні, але спрощені приклади дуже важливі
    • вітається застосування наведених концепцій
  • посилання на корисні ресурси - це добре
  • вітаються невеликі відступи до того, як ОС використовують функції підкачки
  • Пояснення щодо PAE та PSE вітаються
  • вітаються невеликі відступи в x86_64

Пов’язані запитання та чому, на мою думку, це не дурі:


1
Це має бути позначено як "faq" і позначено як "wiki-спільнота".
Kerrek SB

@KerrekSB Я насправді не знаю, як вирішити такі запитання. Відповіді повинні бути вікі спільноти це що? Я не міг знайти faqтег.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

3
Я б сказав, що коротка відповідь: "прочитайте Том 3, Розділ 4: Підказка в Інструкції Intel". Це досить чітко, стисло і добре написано, і воно не стає більш авторитетним.
Kerrek SB

4
@KerrekSB Я погоджуюсь, що посібник зрозумілий та авторитетний, але він був занадто жорстким, оскільки для першого читання для мене мені потрібні були прості та конкретні приклади + обгрунтування, щоб краще зрозуміти речі.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Відповіді:


144

Версія цієї відповіді з приємним TOC та більше змісту .

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

Зразок коду

Мінімальний приклад: https://github.com/cirosantilli/x86-bare-metal-examples/blob/5c672f73884a487414b3e21bd9e579c67cd77621/paging.S

Як і все інше в програмуванні, єдиний спосіб зрозуміти це - грати з мінімальними прикладами.

Що робить цю "важку" тему тим, що мінімальний приклад великий, тому що вам потрібно створити власну маленьку ОС.

Інструкція Intel

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

Корпорація Intel описує підкачки у Посібнику із програмування системного програмування, том 3, том 3 - 325384-056US, вересень 2015 року Розділ 4 " ".

Особливо цікавим є малюнок 4-4 "Формати записів CR3 та структури підкачки з 32-розрядною підкачкою", де наводяться ключові структури даних.

MMU

Підкачка здійснюється блоком керування пам'яттю (MMU), частиною ЦП. Як і багато інших (наприклад, співпроцесор x87 , APIC ), раніше це було окремим чіпом, який згодом був інтегрований в центральний процесор. Але цей термін все ще використовується.

Загальні факти

Логічні адреси - це адреси пам'яті, що використовуються у "звичайному" коді земельної ділянки користувача (наприклад, вміст rsiвmov eax, [rsi] ).

Спочатку сегментація перетворює їх у лінійні адреси, а потім підкачка, а потім перетворює лінійні адреси у фізичні адреси.

(logical) ------------------> (linear) ------------> (physical)
             segmentation                 paging

Здебільшого ми можемо сприймати фізичні адреси як індексацію фактичних комірок апаратної пам'яті оперативної пам'яті, але це не на 100% вірно через:

Підкачка доступна лише в захищеному режимі. Використання підкачки у захищеному режимі є необов’язковим. Виклик сторінки відбувається, якщо PGтрохиcr0 реєстру.

Пейджинг проти сегментації

Однією з основних відмінностей між пейджингом та сегментацією є те, що:

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

Це головна перевага пейджингової сторінки, оскільки шматки однакового розміру роблять речі більш керованими.

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

Застосування

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

  • обидві програми не повинні нічого знати про іншу
  • пам'ять обох програм може зростати і зменшуватися за потреби
  • перемикання між програмами відбувається дуже швидко
  • одна програма ніколи не може отримати доступ до пам'яті іншого процесу

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

Апаратне впровадження

Як і сегментація в захищеному режимі (де зміна реєстру сегментів викликає навантаження з GDT або LDT), апаратне забезпечення пейджингового зв'язку використовує структури даних у пам'яті для виконання своєї роботи (таблиці сторінок, каталоги сторінок тощо).

Формат цих структур даних фіксується апаратним забезпеченням , але операційна система повинна правильно налаштувати та керувати цими структурами даних в оперативній пам'яті та повідомити апаратному забезпеченню, де їх знайти (черезcr3 ).

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

Приклад: спрощена однорівнева система підкачки

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

Таблиці сторінок

ОС може дати їм такі таблиці сторінок:

Таблиця сторінок, надана ОС 1 процесу 1:

RAM location        physical address   present
-----------------   -----------------  --------
PT1 + 0       * L   0x00001            1
PT1 + 1       * L   0x00000            1
PT1 + 2       * L   0x00003            1
PT1 + 3       * L                      0
...                                    ...
PT1 + 0xFFFFF * L   0x00005            1

Таблиця сторінок, надана ОС 2 процесу 2:

RAM location       physical address   present
-----------------  -----------------  --------
PT2 + 0       * L  0x0000A            1
PT2 + 1       * L  0x0000B            1
PT2 + 2       * L                     0
PT2 + 3       * L  0x00003            1
...                ...                ...
PT2 + 0xFFFFF * L  0x00004            1

Де:

  • PT1і PT2: початкове положення таблиць 1 і 2 на оперативній пам'яті

    Приклади значень: 0x00000000, 0x12345678і т.д.

    Саме ОС визначає ці значення.

  • L: довжина запису таблиці сторінок.

  • present: означає, що сторінка присутня в пам'яті.

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

--------------> 0xFFFFFFFF


--------------> PT1 + 0xFFFFF * L
Page Table 1
--------------> PT1


--------------> PT2 + 0xFFFFF * L
Page Table 2
--------------> PT2

--------------> 0x0

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

Кожен процес не може безпосередньо торкатися будь-яких таблиць сторінок, хоча він може надсилати запити до ОС, які спричиняють модифікацію таблиць сторінок, наприклад, запит на більші сегменти стека або купи.

Сторінка - це фрагмент розміром 4 КБ (12 бітів), а оскільки адреси мають 32 біти, для ідентифікації кожної сторінки потрібно лише 20 бітів (20 + 12 = 32, отже, 5 символів у шістнадцятковій позначці). Це значення фіксується обладнанням.

Записи таблиці сторінок

Таблиця сторінок - це ... таблиця записів таблиці сторінок!

Точний формат записів у таблиці визначається обладнанням .

У цьому спрощеному прикладі записи таблиці сторінок містять лише два поля:

bits   function
-----  -----------------------------------------
20     physical address of the start of the page
1      present flag

так що в цьому прикладі дизайнери апаратного забезпечення могли вибрати L = 21.

Більшість записів таблиці реальних сторінок мають інші поля.

Було б недоцільно вирівнювати речі на 21 біт, оскільки пам’ять адресується байтами, а не бітами. Отже, навіть у цьому випадку потрібні лише 21 біт, дизайнери апаратного забезпечення, мабуть, вирішать L = 32зробити доступ швидшим і просто зарезервують біти, що залишилися, для подальшого використання. Фактичне значення для Lx86 становить 32 біти.

Переклад адреси в однорівневій схемі

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

Коли ОС хоче , щоб активізувати процес 1, встановлює , cr3щоб PT1, початок таблиці для одного процесу.

Якщо Процес 1 хоче отримати доступ до лінійної адреси 0x00000001, апаратна схема підкачки автоматично робить для ОС наступне:

  • розділити лінійну адресу на дві частини:

    | page (20 bits) | offset (12 bits) |
    

    Отже, у цьому випадку ми мали б:

    • сторінка = 0x00000
    • зміщення = 0x001
  • загляньте в таблицю сторінок 1, оскільки cr3вказує на неї.

  • шукати запис, 0x00000тому що це частина сторінки.

    Апаратне знає, що цей запис знаходиться за адресою оперативної пам'яті PT1 + 0 * L = PT1.

  • оскільки він присутній, доступ є дійсним

  • по таблиці сторінок, розташування номера сторінки 0x00000знаходиться 0x00001 * 4K = 0x00001000.

  • щоб знайти остаточну фізичну адресу, нам просто потрібно додати зміщення:

      00001 000
    + 00000 001
      -----------
      00001 001
    

    тому що 00001це фізична адреса сторінки, яку шукають у таблиці, і 001є зміщенням.

    Як вказує назва, до зміщення завжди додається просто фізична адреса сторінки.

  • потім апаратне забезпечення отримує пам’ять у цьому фізичному місці.

Таким же чином для процесу 1 відбудуться такі переклади:

linear     physical
---------  ---------
00000 002  00001 002
00000 003  00001 003
00000 FFF  00001 FFF
00001 000  00000 000
00001 001  00000 001
00001 FFF  00000 FFF
00002 000  00002 000
FFFFF 000  00005 000

Наприклад, при зверненні до адреси 00001000частина сторінки 00001апаратне забезпечення знає, що запис таблиці сторінок знаходиться за адресою оперативної пам'яті: PT1 + 1 * L(1 через частину сторінки), і саме там вона її буде шукати.

Коли ОС хоче перейти на процес 2, все, що їй потрібно зробити, це cr3вказати на сторінку 2. Це все так просто!

Тепер для процесу 2 відбудуться такі переклади:

linear     physical
---------  ---------
00000 002  00001 002
00000 003  00001 003
00000 FFF  00001 FFF
00001 000  00000 000
00001 001  00000 001
00001 FFF  00000 FFF
00003 000  00003 000
FFFFF 000  00004 000

Одна і та ж лінійна адреса перекладається на різні фізичні адреси для різних процесів , залежно лише від значення всередині cr3.

Таким чином кожна програма може очікувати, що її дані почнуться в 0і закінчаться о FFFFFFFF, не турбуючись про точні фізичні адреси.

Помилка сторінки

Що робити, якщо Процес 1 намагається отримати доступ до адреси всередині сторінки, якої немає?

Апаратне забезпечення повідомляє програмне забезпечення через виняток помилки сторінки.

Тоді, як правило, ОС повинна зареєструвати обробник винятків, щоб вирішити, що потрібно зробити.

Можливо, доступ до сторінки, якої немає в таблиці, є помилкою програмування:

int is[1];
is[2] = 1;

але можуть бути випадки, коли це прийнятно, наприклад у Linux, коли:

  • програма хоче збільшити свій стек.

    Він просто намагається отримати доступ до певного байта в заданому можливому діапазоні, і якщо ОС задоволена, вона додає цю сторінку до адресного простору процесу.

  • сторінку було замінено на диск.

    ОС повинна буде виконати певну роботу за процесами назад, щоб повернути сторінку в оперативну пам’ять.

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

    Наприклад, у Linux, коли присутній = 0:

    • якщо всі поля запису таблиці сторінок дорівнюють 0, недійсна адреса.

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

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

Спрощення

Спрощення реальності, які полегшують розуміння цього прикладу:

  • усі справжні пейджингові схеми використовують багаторівневу пейджингову інформацію для економії місця, але це показало просту однорівневу схему.

  • таблиці сторінок містили лише два поля: 20-бітову адресу та 1-бітний присутній прапор.

    Таблиці реальних сторінок містять загалом 12 полів, а отже, інші функції, які були пропущені.

Приклад: багаторівнева схема підкачки

Проблема однорівневої схеми підкачки полягає в тому, що вона займе занадто багато оперативної пам'яті: 4G / 4K = 1M записів на процес. Якщо кожен запис має 4 байти, це зробить 4 мільйони на процес , що занадто багато навіть для настільного комп’ютера: ps -A | wc -lговорить, що зараз я запускаю 244 процеси, тож це займе близько 1 ГБ моєї оперативної пам’яті!

З цієї причини розробники x86 вирішили використовувати багаторівневу схему, яка зменшує використання оперативної пам'яті.

Недоліком цієї системи є те, що вона має трохи більший час доступу.

У простій 3-рівневій системі пейджингового виклику, що використовується для 32-розрядних процесорів без PAE, 32 біти адреси поділяються таким чином:

| directory (10 bits) | table (10 bits) | offset (12 bits) |

Кожен процес повинен мати один і лише один пов'язаний з ним каталог сторінок, тому він буде містити щонайменше 2^10 = 1Kзаписи каталогів сторінок, набагато кращі, ніж мінімум 1 М, необхідний для однорівневої схеми.

Таблиці сторінок розподіляються лише за потребою ОС. У кожній таблиці 2^10 = 1Kсторінок є записи в каталозі сторінок

Каталоги сторінок містять ... записи каталогів сторінок! Записи каталогу сторінок є однаковими із записами таблиць сторінок, за винятком того, що вони вказують на адреси оперативної пам'яті таблиць сторінок замість фізичних адрес таблиць . Оскільки ці адреси мають ширину лише 20 біт, таблиці сторінок повинні бути на початку сторінок розміром 4 КБ.

cr3 тепер вказує на розташування в оперативній пам'яті каталогу сторінок поточного процесу замість таблиць сторінок.

Записи таблиць сторінок взагалі не змінюються за однорівневою схемою.

Таблиці сторінок змінюються від однорівневої схеми, оскільки:

  • кожен процес може мати до 1 тис. таблиць сторінок, по одній на запис каталогу сторінки.
  • кожна таблиця сторінок містить рівно 1K записів замість 1M записів.

Причиною використання 10 бітів на перших двох рівнях (а не, скажімо, 12 | 8 | 12) є те, що кожен запис таблиці сторінок має 4 байти. Тоді 2 ^ 10 записів каталогів сторінок та таблиць сторінок добре помістяться на сторінки розміром 4 Кб. Це означає, що для цього швидше та простіше розподіляти та звільняти сторінки.

Переклад адреси в багаторівневій схемі

Каталог сторінок, переданий ОС на процес 1:

RAM location     physical address   present
---------------  -----------------  --------
PD1 + 0     * L  0x10000            1
PD1 + 1     * L                     0
PD1 + 2     * L  0x80000            1
PD1 + 3     * L                     0
...                                 ...
PD1 + 0x3FF * L                     0

Таблиці сторінок, надані для обробки 1 ОС на PT1 = 0x10000000( 0x10000* 4K):

RAM location      physical address   present
---------------   -----------------  --------
PT1 + 0     * L   0x00001            1
PT1 + 1     * L                      0
PT1 + 2     * L   0x0000D            1
...                                  ...
PT1 + 0x3FF * L   0x00005            1

Таблиці сторінок, надані для обробки 1 ОС на PT2 = 0x80000000( 0x80000* 4K):

RAM location      physical address   present
---------------   -----------------  --------
PT2 + 0     * L   0x0000A            1
PT2 + 1     * L   0x0000C            1
PT2 + 2     * L                      0
...                                  ...
PT2 + 0x3FF * L   0x00003            1

де:

  • PD1: початкове положення каталогу сторінок процесу 1 в оперативній пам'яті.
  • PT1і PT2: початкове положення таблиці сторінок 1 і таблиці сторінок 2 для процесу 1 в оперативній пам'яті.

Отже, у цьому прикладі каталог сторінок і таблиця сторінок можуть зберігатися в оперативній пам'яті приблизно так:

----------------> 0xFFFFFFFF


----------------> PT2 + 0x3FF * L
Page Table 1
----------------> PT2

----------------> PD1 + 0x3FF * L
Page Directory 1
----------------> PD1


----------------> PT1 + 0x3FF * L
Page Table 2
----------------> PT1

----------------> 0x0

Давайте перекладемо лінійну адресу 0x00801004поетапно.

Ми вважаємо, що cr3 = PD1, тобто вказує на щойно описаний каталог сторінок.

У двійковій формі лінійна адреса:

0    0    8    0    1    0    0    4
0000 0000 1000 0000 0001 0000 0000 0100

Групування як 10 | 10 | 12дає:

0000000010 0000000001 000000000100
0x2        0x1        0x4

що дає:

  • запис каталогу каталогу сторінок = 0x2
  • запис таблиці сторінок = 0x1
  • зміщення = 0x4

Тож апаратне забезпечення шукає запис 2 каталогу сторінки.

Таблиця каталогів сторінок говорить, що таблиця сторінок знаходиться за адресою 0x80000 * 4K = 0x80000000. Це перший доступ до оперативної пам'яті в процесі.

Оскільки запис таблиці сторінок є 0x1, апаратне забезпечення переглядає запис 1 таблиці сторінок за адресою 0x80000000, який повідомляє, що фізична сторінка знаходиться за адресою 0x0000C * 4K = 0x0000C000. Це другий доступ до оперативної пам'яті в процесі.

Нарешті, апаратне забезпечення підкачки додає зміщення, і кінцевою адресою є 0x0000C004 .

Інші приклади перекладених адрес:

linear    10 10 12 split   physical
--------  ---------------  ----------
00000001  000 000 001      00001001
00001001  000 001 001      page fault
003FF001  000 3FF 001      00005001
00400000  001 000 000      page fault
00800001  002 000 001      0000A001
00801008  002 001 008      0000C008
00802008  002 002 008      page fault
00B00001  003 000 000      page fault

Помилки сторінки трапляються, якщо немає або каталогу каталогу сторінок, або запису таблиці сторінок.

Якщо ОС хоче запустити інший процес одночасно, вона надасть другому процесу окремий каталог сторінок і зв’яже цей каталог з окремими таблицями сторінок.

64-розрядні архітектури

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

x86_64 використовує 48 біт (256 ТБ), а PAE застарілого режиму вже дозволяє 52-бітові адреси (4 ПіБ).

12 із цих 48 бітів вже зарезервовано для зсуву, що залишає 36 бітів.

Якщо взяти підхід на 2 рівні, найкращим розділенням буде два 18-бітових рівня.

Але це означало б, що каталог сторінок містив би 2^18 = 256Kзаписи, які забирали б занадто багато оперативної пам'яті: близько до однорівневого підкачки для 32-розрядних архітектур!

Тому 64-розрядні архітектури створюють ще більше рівнів сторінки, зазвичай 3 або 4.

x86_64 використовує 4 рівні в 9 | 9 | 9 | 12схемі, так що верхній рівень займає лише 2^9записи вищого рівня.

PAE

Розширення фізичної адреси.

З 32 бітами можна вирішити лише 4 ГБ оперативної пам'яті.

Це стало обмеженням для великих серверів, тому Intel представила механізм PAE для Pentium Pro.

Щоб усунути проблему, Intel додала 4 нові адресні рядки, щоб можна було звернутись до 64 Гб.

Структура таблиці сторінок також змінюється, якщо PAE увімкнено. Точний спосіб його зміни залежить від того, увімкнено чи вимкнено PSE.

PAE вмикається та вимикається через PAEбіт cr4.

Навіть якщо загальна адресаційна пам’ять становить 64 Гб, окремі процеси все одно можуть використовувати лише до 4 Гб. Однак ОС може розміщувати різні процеси на різних фрагментах по 4 Гб.

PSE

Розширення розміру сторінки.

Дозволяє розмір сторінок 4M (або 2M, якщо ввімкнено PAE) замість 4K.

PSE вмикається і вимикається через PAEбіт cr4.

Схеми таблиць сторінок PAE та PSE

Якщо активні PAE та PSE, використовуються різні схеми рівня підкачки:

  • відсутність PAE та PSE: 10 | 10 | 12

  • немає PAE і PSE: 10 | 22.

    22 - зміщення на сторінці 4 Мб, оскільки 22 біти адресують 4 Мб.

  • PAE і відсутність PSE: 2 | 9 | 9 | 12

    Причиною дизайну, чому 9 використовується двічі замість 10, є те, що тепер записи більше не вміщуються в 32 біти, які всі заповнюються 20 бітами адреси та 12 значущими або зарезервованими бітами прапора.

    Причина полягає в тому, що 20 біт вже недостатньо для подання адреси таблиць сторінок: 24 біти тепер потрібні через 4 додаткові дроти, додані до процесора.

    Тому дизайнери вирішили збільшити розмір входу до 64 біт, і, щоб вони помістилися в односторінкову таблицю, необхідно зменшити кількість записів до 2 ^ 9 замість 2 ^ 10.

    Початковий 2 - це новий рівень сторінки, який називається Таблиця покажчиків каталогів сторінок (PDPT), оскільки він вказує на каталоги сторінок і заповнює 32-бітну лінійну адресу. PDPT також мають ширину 64 біти.

    cr3тепер вказує на PDPT, які повинні мати на перших чотирьох 4 Гб пам'яті і вирівняні на 32-бітові кратні для ефективного вирішення. Це означає, що тепер cr3має 27 значущих бітів замість 20: 2 ^ 5 для 32 кратних * 2 ^ 27 для заповнення 2 ^ 32 перших 4 Гб.

  • PAE та PSE: 2 | 9 | 21

    Дизайнери вирішили залишити 9-бітне поле, щоб воно вмістилося на одній сторінці.

    Це залишає 23 біти. Залишаючи 2 для PDPT, щоб підтримувати рівномірність справи з корпусом PAE без PSE, залишається 21 для компенсації, що означає, що сторінки мають ширину 2M ​​замість 4M.

TLB

Буфер перекладу підсилювача перекладу (TLB) - це кеш для адрес підкачки.

Оскільки це кеш-пам’ять, він поділяє багато питань дизайну кеш-пам'яті процесора, таких як рівень асоціативності.

Цей розділ повинен описувати спрощений повністю асоціативний TLB з 4 окремими адресами. Зауважте, що, як і інші кеші, реальні TLB зазвичай не є повністю асоціативними.

Основна операція

Після того, як відбувається трансляція між лінійною та фізичною адресою, вона зберігається в TLB. Наприклад, TLB із 4 записів починається у такому стані:

  valid   linear   physical
  ------  -------  ---------
> 0       00000    00000
  0       00000    00000
  0       00000    00000
  0       00000    00000

>Вказує на поточну запис , яку необхідно замінити.

і після того, як лінійна адреса сторінки 00003переведена на фізичну адресу 00005, TLB стає:

  valid   linear   physical
  ------  -------  ---------
  1       00003    00005
> 0       00000    00000
  0       00000    00000
  0       00000    00000

і після другого перекладу 00007на 00009це стає:

  valid   linear   physical
  ------  -------  ---------
  1       00003    00005
  1       00007    00009
> 0       00000    00000
  0       00000    00000

Тепер, якщо 00003потрібно перекласти ще раз, апарат спочатку шукає TLB і знаходить його адресу за допомогою одного доступу до оперативної пам'яті 00003 --> 00005.

Звичайно, 00000це не в TLB, оскільки жоден дійсний запис не містить 00000як ключ.

Політика заміни

Коли заповнюється TLB, старі адреси перезаписуються. Як і для кеш-пам'яті процесора, політика заміни є потенційно складною операцією, але простою та обґрунтованою евристикою є видалення найменш нещодавно використовуваного запису (LRU).

З LRU, починаючи зі стану:

  valid   linear   physical
  ------  -------  ---------
> 1       00003    00005
  1       00007    00009
  1       00009    00001
  1       0000B    00003

додавання 0000D -> 0000Aдасть:

  valid   linear   physical
  ------  -------  ---------
  1       0000D    0000A
> 1       00007    00009
  1       00009    00001
  1       0000B    00003

КАМ

Використання TLB робить переклад швидшим, оскільки початковий переклад займає один доступ на рівень TLB , що означає 2 на простій 32-бітовій схемі, але 3 або 4 на 64-бітній архітектурі.

TLB, як правило, реалізується як дорогий тип оперативної пам'яті, що називається адресною до вмісту пам'яттю (CAM). CAM реалізує асоціативну карту на апаратному забезпеченні, тобто структуру, яка отримує ключ (лінійну адресу), отримує значення.

Зіставлення також можуть бути реалізовані на адресах оперативної пам'яті, але для зіставлення CAM може знадобитися набагато менше записів, ніж відображення оперативної пам'яті.

Наприклад, карта, на якій:

  • і ключі, і значення мають 20 бітів (у випадку простих схем підкачки)
  • щонайбільше потрібно зберігати 4 значення

може зберігатися в TLB з 4 записами:

linear   physical
-------  ---------
00000    00001
00001    00010
00010    00011
FFFFF    00000

Однак, щоб реалізувати це за допомогою оперативної пам'яті, було б потрібно мати 2 ^ 20 адрес :

linear   physical
-------  ---------
00000    00001
00001    00010
00010    00011
... (from 00011 to FFFFE)
FFFFF    00000

що було б навіть дорожче, ніж використання TLB.

Недійсні записи

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

X86 також пропонує invlpgінструкцію, яка явно анулює окремий запис TLB. Інші архітектури пропонують ще більше інструкцій щодо недійсних записів TLB, таких як скасування всіх записів у заданому діапазоні.

Деякі процесори x86 виходять за межі вимог специфікації x86 і забезпечують більшу узгодженість, ніж вона гарантує, між зміною запису таблиці сторінок та її використанням, коли він ще не був кешований у TLB . Очевидно, Windows 9x покладався на це для коректності, але сучасні процесори AMD не забезпечують узгоджених сторінок. Процесори Intel роблять це, хоча для цього їм потрібно виявляти помилкові спекуляції. Скористатися цим - це, мабуть, погана ідея, оскільки, мабуть, багато чого не виграєш, і великий ризик спричинити тонкі проблеми, що залежать від часу, які важко налагодити.

Використання ядра Linux

Ядро Linux широко використовує функції підкачки x86, щоб дозволити швидкі перемикання процесів з невеликою фрагментацією даних.

В v4.2, загляньте під arch/x86/:

  • include/asm/pgtable*
  • include/asm/page*
  • mm/pgtable*
  • mm/page*

Здається, не існує жодних структур, що представляють сторінки, лише макроси: include/asm/page_types.hце особливо цікаво. Витяг:

#define _PAGE_BIT_PRESENT   0   /* is present */
#define _PAGE_BIT_RW        1   /* writeable */
#define _PAGE_BIT_USER      2   /* userspace addressable */
#define _PAGE_BIT_PWT       3   /* page write through */

arch/x86/include/uapi/asm/processor-flags.hвизначає CR0, і зокрема PGбітове положення:

#define X86_CR0_PG_BIT      31 /* Paging */

Бібліографія

Безкоштовно:

  • rutgers-pxk-416 глава "Управління пам'яттю: конспекти лекцій"

    Хороший історичний огляд методів організації пам’яті, що використовувались старшими ОС.

Невільні:

  • bovet05 глава " Адресація пам'яті"

    Розумне введення в адресування пам’яті x86. Не вистачає кількох добрих і простих прикладів.


Чудова відповідь, але мені все ще незрозуміло, як приймається рішення про LRU. Викликання ОС при кожному зверненні до сторінки, відмінної від MRU, здається дорогим. Крім того, я міг бачити обладнання, що переупорядковує таблицю сторінок для LRU, що може бути небезпечним для одночасних програм. Чи є це правильно? Як ОС знає, яка сторінка є LRU, коли відбувається помилка сторінки?
Кейнан 19.03.15

@Keynan Я думаю, що це робить апаратне забезпечення, тому витрачений час не турбує. Що стосується паралельності, я не знаю, як це управляється. Я думаю, що є один CR3 та кеш на процесор, і ОС просто повинна переконатися, що сторінки пам’яті не перекриваються.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
real TLBs are not usually fully associative... The TLB is usually implemented as … CAMЧи не суперечливі ці два твердження?
a3f

>>> x86_64 використовує 4 рівні в 9 | 9 | 9 | 12 схема повинна бути 9 | 9 | 9 | 9 | 12?
monklof

@monklof Я вважаю, що це правильно: 9 9 9 12 вже дозволяє 512 Гб оперативної пам'яті. Схема 5 рівня - це нещодавніша розробка, спрямована лише на сервери, про що згадується у відповіді на моєму веб-сайті, який є більш сучасним.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

22

Ось дуже коротка відповідь на високому рівні:

Процесор x86 працює в одному з декількох можливих режимів (приблизно: реальний, захищений, 64-розрядний). Кожен режим може використовувати одну з декількох можливих моделей адресації пам'яті (але не кожен режим може використовувати кожну модель), а саме: адресацію в реальному режимі, сегментовану адресацію та плосколінійну адресацію.

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

Тепер режим адресації пам'яті надає значення операндам пам'яті машинних інструкцій (наприклад mov DWORD PTR [eax], 25, який зберігає 32-бітове (відоме dword) ціле число, що має значення 25, у пам’яті, адреса якої зберігається в eax32-бітному регістрі). При плосколінійній адресації це число в eaxдозволено працювати в одному суміжному діапазоні від нуля до максимального значення (у нашому випадку це 2 32  - 1).

Однак плосколінійна адресація може бути як посторінковою, так і не посторінковою . Без підкачки адреса безпосередньо стосується фізичної пам’яті. За допомогою підкачки блок управління пам’яттю процесора (або MMU) прозоро подає потрібну адресу (тепер її називають віртуальною адресою ) у механізм пошуку, так звані таблиці сторінок , і отримує нове значення, яке трактується як фізична адреса. Оригінальна операція тепер працює з цією новою, перекладеною адресою у фізичній пам’яті, хоча користувач бачить лише віртуальну адресу.

Ключовою перевагою підкачки є те, що таблицями сторінок керує операційна система. Таким чином, операційна система може довільно змінювати та замінювати таблиці сторінок, наприклад, при "переключенні завдань". Він може зберігати цілу колекцію таблиць сторінок, по одній для кожного "процесу", і всякий раз, коли вирішує, що певний процес збирається запускатися на даному процесорі, він завантажує таблиці сторінок процесу в MMU цього процесора (кожен процесор має свою набір таблиць сторінок). Результатом є те, що кожен процес бачить власний віртуальний адресний простір, який виглядає однаково, незалежно від того, які фізичні сторінки були вільними, коли ОС повинна була виділити для нього пам’ять. Він ніколи не знає про пам'ять будь-якого іншого процесу, оскільки не може отримати безпосередній доступ до фізичної пам'яті.

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

І на випадок, якщо ви турбуєтесь, що процес може просто вимкнути підкачування або спробувати змінити таблиці сторінок: Це заборонено, оскільки x86 реалізує рівні привілеїв (так звані "кільця"), а код користувача виконується на рівні привілеїв, який є занадто низьким, щоб дозволити це для модифікації таблиць сторінок процесора.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.