Глобальная таблица дескрипторов
В этой статье есть несколько проблем. Пожалуйста, помогите улучшить его или обсудите эти проблемы на странице обсуждения . ( Узнайте, как и когда удалять эти шаблонные сообщения )
|
Таблица глобальных дескрипторов ( GDT ) — это структура данных, используемая процессорами Intel x86 , начиная с 80286, для определения характеристик различных областей памяти, используемых во время выполнения программы, включая базовый адрес, размер и права доступа, такие как возможность исполнения и записи. Эти области памяти называются сегментами в терминологии Intel.
Описание
[ редактировать ]GDT представляет собой таблицу из 8-байтовых записей. Каждая запись может относиться к дескриптору сегмента , сегменту состояния задачи (TSS), таблице локальных дескрипторов (LDT) или шлюзу вызова . Шлюзы вызовов были разработаны для передачи управления между уровнями привилегий x86, хотя этот механизм не используется в большинстве современных операционных систем.
Существует также таблица локальных дескрипторов (LDT). В GDT можно определить несколько LDT, но в каждый момент времени только один из них является текущим: обычно он связан с текущей задачей. В то время как LDT содержит сегменты памяти, которые являются частными для конкретного процесса, GDT содержит глобальные сегменты. Процессоры x86 имеют средства автоматического переключения текущего LDT при определенных машинных событиях, но не имеют средств автоматического переключения GDT.
Каждый доступ к памяти, выполняемый процессом, всегда осуществляется через сегмент. На процессоре 80386 и более поздних версиях из-за 32-битных смещений и ограничений сегментов можно сделать так, чтобы сегменты покрывали всю адресуемую память, что делает адресацию относительно сегмента прозрачной для пользователя.
Чтобы ссылаться на сегмент, программа должна использовать его индекс внутри GDT или LDT. Такой индекс называется селектором сегмента (или селектором). селектор должен быть загружен в регистр сегмента Для использования . Помимо машинных инструкций, которые позволяют устанавливать/получать положение GDT и таблицы дескрипторов прерываний (IDT) в памяти, каждая машинная инструкция, ссылающаяся на память, имеет неявный сегментный регистр, иногда два. В большинстве случаев этот регистр сегмента можно переопределить, добавив префикс сегмента перед инструкцией.
При загрузке селектора в регистр сегмента запись GDT или LDT считывается во время загрузки и кэшируется свойства сегмента в скрытом регистре. Последующие изменения в GDT или LDT не вступят в силу до перезагрузки регистра сегмента.
GDT в 64-битной версии
[ редактировать ]GDT по-прежнему присутствует в 64-битном режиме; GDT должен быть определен, но обычно никогда не изменяется и не используется для сегментации. Размер регистра был расширен с 48 до 80 бит, а 64-битные дескрипторы всегда «плоские» (таким образом, с 0x0000000000000000 до 0xFFFFFFFFFFFFFFFF). Однако база FS и GS не ограничена 0, и они продолжают использоваться в качестве указателей на смещение таких элементов, как блок среды процесса и блок информации о потоке.
Если системный бит (4-й бит поля доступа) очищен, размер дескриптора составит 16 байт вместо 8. Это связано с тем, что даже несмотря на то, что сегменты кода/данных игнорируются, TSS не игнорируется, но указатель TSS может быть проигнорирован. Длина 64 бита, поэтому дескриптору требуется больше места для вставки старшего двойного слова указателя TSS.
64-битные версии Windows запрещают подключение GDT; попытка сделать это приведет к проверке машины на наличие ошибок . [1]
Таблица локальных дескрипторов
[ редактировать ]Таблица локальных дескрипторов ( LDT ) — это таблица памяти, используемая в архитектуре x86 в защищенном режиме и содержащая дескрипторы сегментов памяти , так же, как и GDT: начало адреса в линейной памяти, размер, исполняемость, возможность записи, привилегии доступа, фактическое присутствие в памяти, и т. д.
LDT являются братьями и сестрами Глобальной таблицы дескрипторов (GDT), и каждый из них определяет до 8192 сегментов памяти, доступных для программ. Обратите внимание, что в отличие от GDT, нулевая запись является допустимой записью и может использоваться как любая другая запись LDT. Также обратите внимание, что в отличие от GDT, LDT нельзя использовать для хранения определенных системных записей: TSS или LDT. Однако шлюзы вызовов и шлюзы задач подходят.
История
[ редактировать ]На процессорах x86, не имеющих функции подкачки, таких как Intel 80286 , LDT необходим для реализации отдельных адресных пространств для нескольких процессов. Обычно для каждого пользовательского процесса будет один LDT, описывающий частную память, тогда как общая память и память ядра будут описываться GDT. Операционная система переключит текущий LDT при планировании нового процесса, использовании машинной инструкции LLDT или при использовании TSS . Напротив, GDT обычно не переключается (хотя это может произойти, если мониторы виртуальных машин, такие как VMware на компьютере работают ).
Отсутствие симметрии между обеими таблицами подчеркивается тем фактом, что текущий LDT может автоматически включаться при определенных событиях, особенно если используется многозадачность на основе TSS , тогда как для GDT это невозможно. LDT также не может хранить определенные привилегированные типы сегментов памяти (например, TSS). Наконец, LDT фактически определяется дескриптором внутри GDT, тогда как GDT напрямую определяется линейным адресом.
Создание общей памяти с помощью GDT имеет некоторые недостатки. Примечательно, что такая память видна каждому процессу и имеет равные права. Чтобы ограничить видимость и дифференцировать защиту разделяемой памяти, например, чтобы разрешить доступ только для чтения для некоторых процессов, можно использовать отдельные записи LDT, указывающие на одни и те же области физической памяти и создаваемые только в LDT процессов, которые запросили доступ к данной общей области памяти.
Записи LDT (и GDT), которые указывают на идентичные области памяти, называются псевдонимами . Псевдонимы также обычно создаются для того, чтобы получить доступ для записи к сегментам кода: для записи нельзя использовать селектор исполняемого файла. (Программы защищенного режима, созданные в так называемой модели крошечной памяти , где все находится в одном и том же сегменте памяти, должны использовать отдельные селекторы для кода и данных/стека, что делает оба селектора технически «псевдонимами».) В случае GDT псевдонимы также создаются для получения доступа к системным сегментам, таким как TSS.
Сегменты имеют в своих дескрипторах флаг «Присутствовать», позволяющий удалить их из памяти, если возникнет такая необходимость. Например, сегменты кода или неизмененные сегменты данных можно выбросить, а измененные сегменты данных можно выгрузить на диск. Однако, поскольку целые сегменты должны работать как единое целое, необходимо ограничить их размер, чтобы обеспечить своевременную замену. Однако использование сегментов меньшего размера, которые легче заменять, означает, что регистры сегментов необходимо перезагружать чаще, что само по себе является трудоемкой операцией.
Современное использование
[ редактировать ]Микропроцессор Intel 80386 представил подкачку — выделение отдельных страниц физической памяти (которые сами по себе являются очень маленькими единицами памяти) по одним и тем же виртуальным адресам, с тем преимуществом, что подкачка диска происходит намного быстрее и эффективнее, чем подкачка сегментов. Поэтому современные 32-битные операционные системы x86 очень мало используют LDT, в основном для запуска устаревшего 16-битного кода.
Если 16-битный код необходимо запускать в 32-битной среде при совместном использовании памяти (это происходит, например, при запуске программ OS/2 1.x в OS/2 2.0 и более поздних версиях), LDT должен быть написан таким образом, чтобы каждый Плоский (страничный) адрес также имеет селектор в LDT (обычно это приводит к тому, что LDT заполняется записями размером 64 КиБ). Этот метод иногда называют тайлингом LDT . Ограниченный размер LDT означает, что виртуальное плоское адресное пространство должно быть ограничено 512 мегабайтами (8191 x 64 КиБ) - именно это и происходит в OS/2, хотя это ограничение было исправлено в версии 4.5. Также необходимо убедиться, что объекты, выделенные в 32-битной среде, не пересекают границы 64 КиБ; это приводит к некоторой потере адресного пространства.
Если 32-битный код не должен передавать произвольные объекты памяти в 16-битный код, например, предположительно в эмуляции OS/2 1.x, присутствующей в Windows NT Windows 3.1 , или в слое эмуляции , нет необходимости искусственно ограничивать размер 32-битного адресного пространства.
Ссылки
[ редактировать ]- ^ «Политика установки исправлений для систем на базе x64» . 8 октября 2009 г. Архивировано из оригинала 19 января 2022 г. . Проверено 11 декабря 2020 г.
Если операционная система обнаружит одну из этих модификаций или любое другое несанкционированное исправление, она выполнит проверку ошибок и завершит работу системы.
Внешние ссылки
[ редактировать ]- Руководство разработчика программного обеспечения для архитектуры Intel
- Таблица GDT. Архивировано 17 октября 2009 г. на Wayback Machine на OSDev.org.
- Учебное пособие по GDT , заархивировано 14 февраля 2009 г. на Wayback Machine на OSDev.org.
- Учебное пособие Брана по Kernel Dev GDT, заархивировано 3 февраля 2008 г. на Wayback Machine.
- Защищенный режим BrokenThorn. Архивировано 23 апреля 2018 г. на Wayback Machine.