Открыть сервис

Дескриптор сегмента

Дескриптор сегмента — это структура данных, используемая в архитектурах x86 (начиная с Intel 80286) и x86-64 для описания сегмента памяти. Дескриптор определяет базовый адрес, размер, тип доступа и права на сегмент, обеспечивая механизм сегментации памяти. В отличие от простого сегментирования, где адрес вычисляется из сегментного регистра и смещения, дескрипторная модель позволяет операционной системе контролировать доступ к памяти на уровне отдельных сегментов, поддерживая многозадачность и защиту.

История

Концепция дескрипторов сегментов возникла в рамках развития архитектуры x86, когда процессоры Intel перешли от 16-битного режима реального адреса (Real Mode) к 32-битному защищённому режиму (Protected Mode). В реальном режиме сегментный регистр хранил 16-битный адрес, который сдвигался на 4 бита влево и складывался с 16-битным смещением, давая 20-битный физический адрес. Это не обеспечивало никакой защиты памяти.

В 1982 году процессор Intel 80286 ввёл защищённый режим, где сегментные регистры стали указывать на дескрипторы, хранящиеся в таблицах дескрипторов. Это позволило задавать 24-битные базовые адреса и 16-битные лимиты, а также уровни привилегий. С появлением 32-битных процессоров (Intel 80386) дескрипторы были расширены до 32-битных базовых адресов и 20-битных лимитов, а также добавлены биты гранулярности (4 КБ или 1 байт).

В архитектуре x86-64 (AMD64, Intel 64) сегментация в длинном режиме (Long Mode) практически не используется для адресации памяти, но дескрипторы сегментов остаются необходимыми для управления сегментными регистрами (CS, SS, DS, ES, FS, GS) и определения их атрибутов (например, кольца привилегий).

Структура дескриптора сегмента

В архитектуре x86 дескриптор сегмента занимает 8 байт (64 бита) и имеет следующую структуру:

ПолеРазмер (бит)Описание
Base (15:0)16Младшие 16 бит базового адреса
Base (23:16)8Следующие 8 бит базового адреса
Base (31:24)8Старшие 8 бит базового адреса
Limit (15:0)16Младшие 16 бит лимита
Limit (19:16)4Старшие 4 бита лимита
Type4Тип сегмента (код, данные, системный)
S1Дескриптор системы (0 — системный, 1 — код/данные)
DPL2Уровень привилегий (0 — наивысший, 3 — наименьший)
P1Присутствие сегмента (Present)
G1Гранулярность (0 — 1 байт, 1 — 4 КБ)
D/B1Размер операнда (0 — 16 бит, 1 — 32 бита)
L1Длинный режим (только для x86-64)
AVL1Доступно для системы

Пояснения:

  • Base — 32-битный физический адрес начала сегмента.
  • Limit — 20-битный размер сегмента. При G=0 лимит задаётся в байтах (до 1 МБ), при G=1 — в блоках по 4 КБ (до 4 ГБ).
  • Type — определяет тип сегмента: для кода (чтение/выполнение), для данных (чтение/запись), для системных объектов (TSS, LDT, шлюзы).
  • S — отличает дескрипторы сегментов кода/данных (S=1) от системных дескрипторов (S=0).
  • DPL — уровень привилегий, определяющий, с какого кольца защиты можно обращаться к сегменту.
  • P — если P=0, сегмент отсутствует в памяти (вызовет исключение при попытке доступа).
  • G — гранулярность: при G=1 лимит умножается на 4096.
  • D/B — для сегментов кода задаёт размер операнда по умолчанию (16 или 32 бита), для сегментов данных — размер стека (SS).
  • L — устанавливается в 1 для 64-битных сегментов в длинном режиме.
  • AVL — зарезервировано для использования операционной системой.

Типы дескрипторов

Дескрипторы сегментов кода и данных (S=1)

  • Сегмент данных (Data Segment): поддерживает чтение и/или запись. Тип может быть «только чтение», «чтение/запись», «расширяющийся вниз» (для стеков).
  • Сегмент кода (Code Segment): поддерживает выполнение и/или чтение. Тип может быть «только выполнение», «выполнение/чтение», «подчинённый» (conforming) — разрешает выполнение с меньшим уровнем привилегий.

Системные дескрипторы (S=0)

  • TSS (Task State Segment): описывает состояние задачи (регистры, стек, ссылки на другие сегменты).
  • LDT (Local Descriptor Table): содержит локальные дескрипторы для конкретной задачи.
  • Call Gate (Шлюз вызова): позволяет переключать уровень привилегий при вызове процедуры.
  • Interrupt Gate (Шлюз прерывания): используется для обработки аппаратных прерываний.
  • Trap Gate (Шлюз ловушки): аналогичен шлюзу прерывания, но не сбрасывает флаг IF.

Таблицы дескрипторов

Дескрипторы хранятся в двух типах таблиц:

  • GDT (Global Descriptor Table): глобальная таблица дескрипторов, доступная всем задачам. Обычно содержит дескрипторы ядра ОС, TSS, LDT и шлюзы.
  • LDT (Local Descriptor Table): локальная таблица, создаваемая для каждой задачи (процесса). Позволяет изолировать сегменты разных процессов.

Адрес и размер GDT хранятся в регистре GDTR, а LDT — в регистре LDTR. Для доступа к сегменту процессор загружает селектор (16-битное значение) в сегментный регистр (CS, SS, DS и т.д.). Селектор содержит индекс в таблице дескрипторов, номер таблицы (GDT или LDT) и уровень привилегий (RPL).

Использование в защищённом режиме

В защищённом режиме (32-битном) каждый сегментный регистр (CS, SS, DS, ES, FS, GS) содержит селектор, который ссылается на дескриптор. При загрузке селектора процессор извлекает дескриптор из GDT или LDT и кэширует его в теневом регистре (shadow register). Последующие обращения к памяти проверяются по закэшированным атрибутам: базовый адрес, лимит, права доступа и уровень привилегий.

Например, при попытке записи в сегмент данных с типом «только чтение» процессор генерирует исключение (General Protection Fault). Это обеспечивает защиту памяти между задачами и ядром ОС.

Использование в длинном режиме (x86-64)

В 64-битном длинном режиме сегментация для адресации памяти отключена: все сегментные регистры, кроме FS и GS, имеют фиксированный базовый адрес 0. Однако дескрипторы сегментов всё ещё используются для:

  • Определения уровня привилегий (кольца защиты) через сегмент кода (CS).
  • Настройки сегментов данных (DS, ES, SS) — их атрибуты (DPL, тип) влияют на проверки доступа.
  • Регистров FS и GS: их базовые адреса могут быть заданы через Model-Specific Registers (MSR) для поддержки локальной памяти потоков (Thread-Local Storage, TLS).

В длинном режиме дескрипторы сегментов кода и данных имеют 64-битную структуру, но лимит игнорируется (считается равным 2^64 - 1). Бит L (Long mode) в дескрипторе кода указывает, что сегмент работает в 64-битном режиме.

Примеры дескрипторов

Дескриптор сегмента кода для 32-битного защищённого режима

  • Base: 0x00000000
  • Limit: 0xFFFFF (при G=1 даёт 4 ГБ)
  • Type: 0xA (выполнение/чтение, не подчинённый)
  • S: 1
  • DPL: 0 (кольцо 0)
  • P: 1
  • G: 1
  • D/B: 1 (32-битный)

Дескриптор сегмента данных для 64-битного длинного режима

  • Base: 0x00000000
  • Limit: 0x00000 (игнорируется)
  • Type: 0x2 (чтение/запись)
  • S: 1
  • DPL: 3 (кольцо 3)
  • P: 1
  • G: 0
  • D/B: 0 (16-битный, но не используется)
  • L: 0 (не длинный режим для данных)

Критика и ограничения

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

  • Сложность управления: операционная система должна поддерживать GDT и LDT, что увеличивает накладные расходы.
  • Ограниченная адресация: в 32-битном режиме база и лимит ограничены 4 ГБ, что недостаточно для современных систем.
  • Несовместимость с плоской моделью памяти: большинство современных ОС (Linux, Windows) используют плоскую модель памяти, где все сегменты имеют одинаковый базовый адрес (0) и лимит (4 ГБ), а сегментация фактически игнорируется.
  • Устаревание в x86-64: в длинном режиме сегментация отключена, и дескрипторы используются только для управления привилегиями и TLS.

Тем не менее, дескрипторы сегментов остаются обязательным элементом архитектуры x86 для обратной совместимости с 16-битным и 32-битным кодом.

Источники

  1. Intel Corporation. Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A: System Programming Guide. 2023. Chapter 3.2: "Protected-Mode Memory Management".
  2. AMD Corporation. AMD64 Architecture Programmer’s Manual, Volume 2: System Programming. 2022. Chapter 4: "Segmentation".
  3. Crawford, J., & Gelsinger, P. Programming the 80386. Sybex, 1987.
  4. Love, R. Linux Kernel Development. 3rd ed. Addison-Wesley, 2010. Chapter 4: "Memory Management".
  5. Таненбаум, Э., Бос, Х. Современные операционные системы. 4-е изд. Питер, 2015. Глава 3: "Управление памятью".
Загружаем BFOmetr…