среда, 24 июня 2009 г.

Важность выравнивания даже на x86

Это перевод Importance of alignment even on x86 machines. Автор: Реймонд Чен.

Иногда доступ к памяти без выравнивания (unaligned memory) может подвесить машину.

Некоторые видео-карты не позволяют вам получать доступ ко всей памяти за раз. Вместо этого вам даётся окно, в которое вы можете выбрать для проецирования одно из нескольких подмножеств видео-памяти ("банк памяти"). Например, видео-карта EGA имела 256 Кб памяти, разделённой в 4 банка по 64 Кб. Если вы хотели получить доступ к памяти в первых 64 Кб, вы должны были выбрать нулевой банк для проецирования в окно, но если вам нужна была память выше 64 Кб, но меньше 128 Кб, то вы должны были выбрать первый банк.

Переключение банков (bank-switching) делает доступ к памяти более сложным. Например, если вы хотите скопировать блок памяти в область памяти с переключением банков, мы должны проверить, не пересекает ли ваш блок границы банков, и если да - разбить копирование всего блока на копирование нескольких кусков. Если вы делаете что-то, что требует не последовательного доступа (скажем, рисуете диагональную линию), то вы должны выяснять, в какой момент ваша линия пересечёт границы банков.

Для упрощения работы, Windows 95 имела драйвер, называемый VFLATD, который делал банк-память "как-бы плоской" для остальной системы. "Уплощение" (flattening) банк-памяти было также жизненно необходимым для поддержки DirectDraw; в частности, метод IDirectDrawSurface.Lock давал вам прямой доступ к (казалось бы) плоскому виду видео-памяти. Например, если приложение хотело увидеть все 256 Кб видео-памяти и писало что-то в первые 64 Кб, то драйвер VFLATD выбирал нулевой банк и проецировал 64 Кб физической памяти окна видео-памяти в первые 64 Кб виртуального пространства в 256 Кб.

Это прекрасно работало, пока все использовали только память с корректным выравниванием. Но если вы пытались обратиться к памяти без выравнивания, вы могли послать VFLATD в бесконечный цикл и подвесить машину.

Предположим, вы делаете обращение к памяти без выравнивания, затрагивая два банка. Этот доступ к памяти никогда не может быть выполнен. При доступе к нижней части возбуждается ошибка страницы (page fault), и VFLATD проецирует в память банк для нижней части, что делает банк для верхней части недоступным. Теперь ошибка страницы возбуждается для верхней части и VFLATD теперь должен спроецировать верхний банк; это отвязывает (unmaps) нижний банк, т.к. в один момент времени у видео-карты с банк-памятью только один банк может быть доступен. Теперь ошибка сраницы генерируется для нижней части, и цикл повторяется снова и снова.

Мораль истории: не нарушайте выравнивание памяти, даже на x86, на котором большинство людей считают "безопасным" нарушать правила выравнивания.

В следующий раз мы рассмотрим другой пример как данные с невеным выравниванием могут создавать баги на x86.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

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

Примечание. Отправлять комментарии могут только участники этого блога.