Противоречивые правила выравнивания для структур и массивов - PullRequest
2 голосов
/ 29 января 2020

Как следует из названия, вопрос касается выравнивания типов агрегатов в x86-64 по Linux.

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

«Предполагая, что каждая таблица страниц [4 КБ, каждый PTE 64b] хранится в памяти в естественно выровненный »физический адрес (т. е. адрес, который является целым числом, кратным размеру таблицы), ..."

Как получилось, что для таблицы страниц (которая по сути является массивом 8-байтовые значения в памяти), правила выравнивания соответствуют не самому большому элементу, а размеру всей таблицы?

Разъяснение приветствуется!
Феликс Lecture slide

Ответы [ 2 ]

6 голосов
/ 29 января 2020

Почему таблицы страниц выровнены по размеру

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

Вы можете убедить самостоятельно это действительно так с несколькими примерами.
Это не совпадение, x86 также следуют этому выравниванию.

Например, в отношении 4-уровневой подкачки для страниц 4 КБ процессоров x86, Page Directory Поле указателя 64-битного адреса имеет ширину 9 бит.
Каждая запись в этой таблице (PDPTE) составляет 64 бита, поэтому размер страницы составляет 4096 КБ, а последняя запись имеет смещение 511 * 8 = 4088 (0xff8 в шестнадцатеричном формате). , поэтому используется не более 12 бит).
Адрес таблицы указателя каталога страниц задается записью PML4, эти записи не указывают младшие 12 битов базы (которые используются для других целей), только верхние биты.
Затем процессор может просто заменить младшие 12 битов в записи PML4 смещением PDPTE, поскольку мы видели, что он имеет размер 12 бит.

Это быстро и дешево сделать аппаратно (без переноса, легко с регистрами).

Предположим, что в стране есть почтовые индексы, состоящие из двух полей: код города (C) и код блока (D), добавленные вместе.
Также предположим, что может быть не более 100 коды блоков для данного города, поэтому D имеет длину 2 цифры.
Требование, чтобы код города был выровнен на 100 (что означает, что две последние цифры C равны нулю), C + D напоминает замену последние две цифры C с D. (1200 + 34 = 12 | 34).

Связь с выравниванием агрегатов

Таблица страниц не рассматривается как агрегат, то есть как массив из 8 байтовых элементов. Он рассматривается как тип его собственного , определенного ISA ЦП, который должен удовлетворять требованиям конкретной части ЦП, которая его использует.
Обходчик страниц находит удобным иметь таблица страниц выровнена по размеру, так что это требование.

Выравнивание агрегатов - это набор правил, используемых компилятором для выделения объектов в памяти, он гарантирует, что выполняется выравнивание каждого элемента, так что инструкции могут получить доступ к любому элементу без штрафов за выравнивание / ошибки.
Единицы выполнения для загрузок и хранилищ являются частью ЦП, отличной от обходчика страниц, поэтому другие потребности.

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

Исключения существуют

Обратите внимание, что профессор пошел долгий путь с объяснением того, что выравнивание по их естественной границе означает для таблиц страниц.
Исключения существуют t, если вам говорят, что данные должны быть выровнены по X, вы можете предположить, что есть какой-то аппаратный трюк / упрощение, и попытаться выяснить, какой из них, но в конце вы просто выполняете выравнивание и идете дальше.

1 голос
/ 30 января 2020

Маргарет объяснила, почему таблицы страниц особенные, я отвечу только на эту другую часть вопроса.


в соответствии с самым большим элементом.

Это также не правило для нормальных структур. Вы хотите max(alignof(member)) не max(sizeof(member)). Поэтому «в соответствии с наиболее выровненным элементом» было бы лучшим способом описать требуемое выравнивание нормальной структуры.

Например, в i386 System V ABI, double имеет sizeof = 8, но alignof = 4 , так что alignof(struct S1) = 4 1

Даже если член char был последним, sizeof(struct S1) все равно должен быть дополнен кратным alignof(), так что все обычные поддерживаются инварианты (например, sizeof( array ) = N * sizeof(struct S1)), и поэтому шаг по sizeof всегда приводит вас к достаточно выровненной границе для начала новой структуры.


Сноска 1: этот ABI был разработан до появления процессоров может эффективно загружать / хранить 8 байтов одновременно. Современные компиляторы пытаются дать двойное и [u] int64_t 8-байтовое выравнивание, например, как глобальные или локальные вне структур. Но правила компоновки структуры ABI фиксируют макет на основе минимального гарантированного выравнивания для любого объекта double или int64_t, который для этих типов равен alignof(T) = 4.

x86-64 Система V имеет alignof (T) = sizeof (T) для всех примитивных типов, включая 8-байтовые. Это делает возможными операции atomi c с любым правильно выровненным int64_t, например, упрощая реализацию C ++ 20 std::atomic_ref, чтобы не проверять достаточное выравнивание. ( Почему целочисленное присваивание для естественно выровненной переменной atomi c на x86? )

...