Сегментная адресация¶
Сегментная адресация — это механизм управления памятью, при котором адресное пространство программы делится на логические блоки (сегменты) переменной длины, а каждый адрес представляется в виде пары, состоящей из номера сегмента и смещения внутри него. В отличие от страничной адресации, где память делится на блоки фиксированного размера (страницы), сегменты могут иметь произвольный размер, соответствующий логической структуре данных (код, данные, стек, куча). Сегментная адресация широко применялась в архитектурах x86 (режим реальных адресов и защищённый режим), а также в операционных системах (OS/2, Multics) и языках программирования (Intel 8086, IBM System/360).
¶История
¶Ранние реализации
Идея сегментации восходит к 1960-м годам, когда в компьютерах IBM System/360 была реализована адресация с использованием сегментов для поддержки многозадачности и защиты памяти. В 1970-х годах в операционной системе Multics (MIT, Bell Labs, General Electric) сегменты использовались как основной способ организации виртуальной памяти, позволяя программам обращаться к большим адресным пространствам, чем физически доступно.
¶Архитектура x86
Наибольшую известность сегментная адресация получила с появлением процессоров Intel 8086 (1978 год). В реальном режиме (Real Mode) 16-битные процессоры использовали сегментные регистры (CS, DS, SS, ES) для формирования 20-битного адреса (1 МБ). Адрес вычислялся как (сегмент × 16) + смещение. Позже, в защищённом режиме (Protected Mode, начиная с Intel 80286), сегменты стали описываться дескрипторами в глобальной (GDT) или локальной (LDT) таблицах, что обеспечивало защиту (уровни привилегий, кольца защиты) и виртуальную память.
¶Современное состояние
В 64-битных архитектурах (x86-64, AMD64) сегментная адресация в её классическом виде (сегментные регистры с дескрипторами) была упрощена. В 64-битном режиме (Long Mode) сегменты CS, DS, ES, SS, FS, GS используются в основном для управления привилегиями (кольца 0 и 3) и для доступа к локальным данным (например, через FS и GS в Windows и Linux для thread-local storage). Основной механизм виртуальной памяти в современных ОС — страничная адресация, а сегментация выполняет вспомогательную роль.
¶Принцип работы
¶Сегмент и смещение
Каждый сегмент — это непрерывный блок памяти с заданным начальным адресом и длиной (лимитом). Логический адрес (или виртуальный адрес) состоит из двух частей:
- Идентификатор сегмента (номер сегмента или селектор) — указывает на дескриптор сегмента в таблице.
- Смещение — относительное положение внутри сегмента (от 0 до лимита).
Физический адрес вычисляется как базовый адрес сегмента + смещение. Если смещение превышает лимит, возникает исключение (ошибка защиты).
¶Таблицы дескрипторов
В защищённом режиме x86 используются две таблицы:
- GDT (Global Descriptor Table) — глобальная таблица дескрипторов, доступная всем задачам. Содержит дескрипторы для ядра, системных сегментов и пользовательских сегментов.
- LDT (Local Descriptor Table) — локальная таблица дескрипторов, уникальная для каждой задачи (процесса). Позволяет изолировать сегменты разных процессов.
Каждый дескриптор содержит:
- Базовый адрес (32 бита в защищённом режиме, 64 бита в Long Mode).
- Лимит (20 бит, с гранулярностью 1 байт или 4 КБ).
- Тип (код, данные, стек, системный).
- Уровень привилегий (DPL, 0–3).
- Флаги (присутствие, доступность, разрешение на запись/чтение).
¶Сегментные регистры
В x86 процессор имеет шесть сегментных регистров:
- CS (Code Segment) — указывает на сегмент кода, содержит текущий уровень привилегий (CPL).
- DS (Data Segment) — сегмент данных по умолчанию.
- SS (Stack Segment) — сегмент стека.
- ES, FS, GS — дополнительные сегменты данных (часто используются для специальных целей, например, FS в Windows для thread-local storage).
При каждом обращении к памяти процессор автоматически использует соответствующий сегментный регистр (например, для выборки инструкции — CS, для стека — SS). Программист может явно указать сегментный префикс (например, mov ax, es:[bx]).
¶Виды сегментной адресации
¶Реальный режим (Real Mode)
- Используется в 16-битных процессорах Intel 8086/80286.
- Адрес:
(сегмент × 16) + смещение(20 бит, до 1 МБ). - Сегментные регистры содержат непосредственное значение (база), а не дескриптор.
- Нет защиты: любой сегмент может быть записан или прочитан, нет контроля привилегий.
- Применялся в DOS и ранних версиях Windows (до Windows 95).
¶Защищённый режим (Protected Mode)
- Введён в Intel 80286 (16-битный) и Intel 80386 (32-битный).
- Адрес:
база из дескриптора + смещение(32 бита, до 4 ГБ). - Используются GDT/LDT, дескрипторы с защитой (DPL, RPL, CPL).
- Поддерживается виртуальная память (страничная адресация может быть включена дополнительно).
- Применялся в Windows NT/2000/XP, Linux (до перехода на 64-битные ядра), OS/2.
¶64-битный режим (Long Mode)
- Введён в AMD64 (2003 год) и Intel 64 (EM64T).
- Сегментная адресация упрощена: сегменты CS, DS, ES, SS, FS, GS используются, но их база и лимит фиксированы (база = 0, лимит = максимальный). Исключение — FS и GS, которые могут иметь ненулевую базу для thread-local storage.
- Адресация в основном плоская (flat model): все сегменты перекрывают всё адресное пространство (64 бита).
- Защита на уровне сегментов сохраняется только для CS (привилегии) и для FS/GS (специальные регистры).
¶Применение
¶Операционные системы
- Windows: в 32-битных версиях (NT, 2000, XP) использовалась плоская модель (flat model) с сегментацией для защиты ядра (кольцо 0) и пользователя (кольцо 3). В 64-битных версиях сегменты используются минимально, в основном для thread-local storage (FS) и для управления привилегиями.
- Linux: в 32-битном режиме Linux использует плоскую модель с четырьмя сегментами (__KERNEL_CS, __KERNEL_DS, __USER_CS, __USER_DS). В 64-битном режиме сегментация ещё более упрощена, но сохраняется для FS (thread-local storage) и для поддержки 32-битных приложений (через CS).
- OS/2: активно использовала сегментную модель, позволяя программам иметь до 16 000 сегментов.
¶Программирование
- Язык ассемблера: в реальном режиме программист явно управляет сегментными регистрами (например,
mov ax, @data; mov ds, ax). В защищённом режиме работа с сегментами скрыта за дескрипторами, но программист может задавать их через GDT. - Защита памяти: сегменты позволяют изолировать код и данные разных процессов, предотвращая несанкционированный доступ (например, сегмент данных одного процесса не может быть прочитан другим процессом, если не настроен общий сегмент).
- Thread-local storage (TLS): в современных ОС (Windows, Linux) сегментные регистры FS (x86) или GS (x86-64) используются для хранения указателя на локальные данные потока, что ускоряет доступ к переменным, уникальным для каждого потока.
¶Преимущества и недостатки
¶Преимущества
- Логическая структура: сегменты соответствуют логическим единицам программы (код, данные, стек), что упрощает управление памятью и защиту.
- Гибкость: сегменты могут иметь произвольный размер, что позволяет эффективно выделять память под структуры данных (например, массивы, строки, таблицы).
- Защита: сегментные дескрипторы поддерживают уровни привилегий (кольца), что позволяет изолировать ядро ОС от пользовательских процессов и предотвращать ошибки доступа.
- Совместимость: сегментная адресация в x86 обеспечивает обратную совместимость с 16-битным кодом (реальный режим) и 32-битным кодом (защищённый режим).
¶Недостатки
- Фрагментация: сегменты переменной длины могут приводить к внешней фрагментации памяти (как в динамическом выделении), что снижает эффективность использования физической памяти.
- Сложность управления: работа с сегментами требует от программиста или ОС управления таблицами дескрипторов и обработки исключений (например, при превышении лимита).
- Производительность: вычисление физического адреса требует дополнительных операций (чтение дескриптора из памяти, проверка лимита, сложение), что может замедлять доступ к памяти по сравнению с плоской адресацией.
- Ограничение размера: в реальном режиме (16-бит) максимальный размер сегмента — 64 КБ, что ограничивает размер программ и данных. В защищённом режиме (32-бит) лимит может быть до 4 ГБ, но это всё равно меньше, чем 64-битное адресное пространство.
¶Сравнение со страничной адресацией
| Параметр | Сегментная адресация | Страничная адресация |
|---|---|---|
| Размер блока | Переменный (от 1 байта до 4 ГБ) | Фиксированный (обычно 4 КБ, 2 МБ, 1 ГБ) |
| Логическая структура | Соответствует логическим модулям (код, данные) | Не зависит от логики программы |
| Защита | На уровне сегментов (DPL, кольца) | На уровне страниц (биты чтения/записи/исполнения) |
| Фрагментация | Внешняя (фрагментация памяти) | Внутренняя (небольшая потеря из-за фиксированного размера) |
| Управление | Требует таблиц дескрипторов (GDT/LDT) | Требует таблиц страниц (page tables) |
| Применение | Защита, изоляция, TLS | Виртуальная память, подкачка, большие адресные пространства |
В современных системах (Windows, Linux, macOS) сегментная и страничная адресации часто используются совместно: сегменты обеспечивают защиту на уровне привилегий (кольца), а страницы — виртуальную память и подкачку.
¶Интересные факты
- В процессорах Intel 8086 сегментная адресация позволяла адресовать до 1 МБ памяти, хотя 16-битные регистры могли адресовать только 64 КБ. Это было достигнуто за счёт сдвига сегмента на 4 бита (умножение на 16).
- В защищённом режиме x86 существует понятие «кольца защиты» (rings): кольцо 0 (самое привилегированное, ядро ОС) и кольцо 3 (наименее привилегированное, пользовательские приложения). Кольца 1 и 2 редко используются, но применялись в OS/2.
- В 64-битном режиме (Long Mode) сегментные регистры CS, DS, ES, SS, FS, GS по-прежнему существуют, но их база и лимит игнорируются для адресации (кроме FS и GS). Это сделано для упрощения и повышения производительности.
- Операционная система Multics (1960-е) была одной из первых, где сегментная адресация использовалась для виртуальной памяти и защиты. Она оказала влияние на разработку Unix и Windows.
¶Источники
- Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A: System Programming Guide.
- AMD64 Architecture Programmer’s Manual, Volume 2: System Programming.
- Таненбаум Э., Бос Х. «Современные операционные системы» (4-е издание), 2015.
- Patterson D., Hennessy J. «Computer Organization and Design: The Hardware/Software Interface» (5th edition), 2013.
- Документация Microsoft Windows Internals (7th edition, 2017).