жизнь программы в терминах постраничной сегментации памяти - PullRequest
3 голосов
/ 18 ноября 2011

У меня запутанное представление о процессе сегментации и подкачки на машинах Linux x86.Будем рады, если некоторые прояснят все этапы, от начала и до конца.

x86 использует технику постраничной сегментации памяти для управления памятью.

Может ли кто-нибудь объяснить, что происходит с моментаисполняемый файл формата .elf загружается с жесткого диска в основную память до момента его смерти.при компиляции исполняемый файл содержит различные разделы (текст, данные, стек, куча, bss).как это будет загружено?как они будут настроены в технике постраничной сегментации памяти.

Хотите знать, как настраиваются таблицы страниц для загруженной программы?Хотел узнать, как настраивается таблица GDT.как регистры загружаются?и почему сказано, что логические адреса (те, которые обрабатываются модулем сегментации MMU, составляют 48 бит (16 бит селектора сегмента + 32-битное смещение), когда это 32-битная машина. Как будут храниться другие 16 бит?любая вещь, доступная из оперативной памяти, должна иметь длину 32 бита или 4 байта, как получить доступ к остальным 16 битам (для загрузки в регистры сегментов)?

Заранее спасибо. Вопрос может иметь много вещей, ноЯ хотел бы получить разъяснения по поводу всего жизненного цикла исполняемого файла. Буду рад, если кто-нибудь ответит, и обсудит это.

Ответы [ 3 ]

2 голосов
/ 18 ноября 2011

В Unix традиционно реализована защита через пейджинг.286+ обеспечивает сегментацию, а 386+ обеспечивает пейджинг.Каждый использует разбиение на страницы, лишь немногие реально используют сегментацию.

В x86 каждый операнд памяти имеет неявный сегмент (поэтому адрес действительно 16-битный селектор + 32-битное смещение), в зависимости от используемого регистра.Таким образом, если вы обращаетесь к [ESP + 8], подразумеваемый регистр сегмента равен SS, если вы обращаетесь к [ESI], подразумеваемый регистр сегмента равен DS, если вы обращаетесь к [EDI+4], подразумеваемый регистр сегмента равен ES, ... Youможет переопределить это с помощью переопределения префикса сегмента.

В Linux и практически во всех современных ОС x86 используется модель плоской памяти (или что-то подобное).В модели с плоской памятью каждый сегмент обеспечивает доступ ко всей памяти с базой 0 и пределом 4 Гб, поэтому вам не нужно беспокоиться о сложностях, возникающих при сегментации.В основном это 4 сегмента: код пространства ядра (RX), данные пространства ядра (RW), код пространства пользователя (RX), данные пространства пользователя (RW).

Файл ELF состоит из нескольких заголовков, которые отображаются в «программных сегментах»и «разделы».Раздел используется для ссылки.Сегменты программы используются для загрузки.Сегменты программы отображаются в память с помощью mmap(), это устанавливает записи таблицы страниц с соответствующими разрешениями.

Теперь механизм подкачки старых процессоров x86 обеспечивает только контроль доступа к RW (разрешение на чтение подразумевает разрешение на выполнение), а сегментацияобеспечил контроль доступа RWX.Разрешение на конец учитывает сегментацию и разбиение на страницы (например, RW (сегмент данных) + R (страница только для чтения) = R (только чтение), а RX (сегмент кода) + R (страница только для чтения) = RX (чтение и чтение).выполнение)).

Таким образом, есть некоторые исправления, которые обеспечивают предотвращение выполнения с помощью сегментации: например, OpenWall предоставил неисполняемый стек путем сокращения сегмента кода (с разрешением на выполнение) и специальной эмуляцией в обработчике ошибок страницы для чего-либодля этого требовалось выполнение с большим адресом памяти (например: батуты GCC, автоматически модифицированный код, созданный в стеке для эффективной реализации вложенных функций).

1 голос
/ 18 ноября 2011

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

  1. Перевод логического адреса вида 16-bit segment selector value:16/32/64-bit segment offset value, то есть пары из 2 чисел в 32/64-bit virtual address.
  2. Перевод virtual address в 32/64-bit physical address.

Логические адреса - это то, с чем ваши приложения работают напрямую.Затем следует приведенный выше двухэтапный перевод их в физические адреса, которые понимает ОЗУ.

На первом шаге GDT (или это может быть LDT, зависит от значения селектора) индексируется селекторомнайти базовый адрес и размер соответствующего сегмента.Виртуальный адрес будет суммой базового адреса сегмента и смещения.Размер сегмента и другие элементы в дескрипторах сегмента необходимы для обеспечения защиты.

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

Это касается механизмов.

Теперь во многих ОС x86 используются селекторы сегментов, которые используютсяпоскольку приложения являются фиксированными, они одинаковы во всех них, они никогда не изменяются и указывают на дескрипторы сегментов, у которых базовые адреса равны 0 и размеры равны возможному максимуму (например, 4 ГБ в не 64-битных режимах).Такая установка GDT фактически означает, что первый шаг не выполняет полезной работы, а смещенная часть логического адреса преобразуется в виртуально равный виртуальный адрес.

Это делает значения селектора сегмента практически бесполезными.Они все еще должны быть загружены в регистры сегментов ЦП (в не 64-битных режимах, по крайней мере, в CS, SS, DS и ES), но после этого момента их можно забыть.

Это все (кроме деталей, связанных с Linux и формата ELF), поясняется или непосредственно следует из руководств по процессорам Intel и x86 для процессоров AMD.Там вы найдете еще много деталей.

0 голосов
/ 18 ноября 2011

Возможно, прочитайте Assembly HOWTO . Когда процесс Linux начинает выполнять исполняемый файл ELF с помощью системного вызова execve , он по существу (своего рода) mmap содержит некоторые сегменты (и инициализирует регистры). и крошечная часть стека). Читайте также SVR4 x86 ABI дополнение и его x86-64 вариант . Не забывайте, что процесс Linux видит отображение памяти только для своего адресного пространства и заботится только о виртуальной памяти

Есть много хороших книг по Операционным системам (= ОС) ядрам , в частности A.Tanenbaum & M.Bach и некоторые в ядре Linux

Примечание: сегментные регистры почти (почти) не используются в Linux.

...