Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Аппаратное обеспечение

Что каждый программист должен знать о памяти.

Часть 2: Кэш-память процессора

Оригинал: "Memory part 2: CPU caches"
Автор: Ulrich Drepper
Дата публикации: October 1, 2007
Перевод: Н.Ромоданов
Дата перевода: апрель 2012 г.
Назад Оглавление Вперед

3.4.1 Самомодифицирующийся код

В начале эры компьютеров память была дорогой. Люди шли на все, чтобы уменьшить размер программы и оставить больше места для данных. Одним из часто используемых трюков было изменение самой программы по ходу ее исполнения. Такой самомодифицирующийся код (Self Modifying Code - SMC) еще иногда встречается, причем сегодня это связано в основном с задачами повышения производительности или эксплойтами безопасности.

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

Наконец, поскольку в процессоре для простоты и потому, что это верно в 99,9999999% всех случаев, предполагается, что страницы с кодом не изменяются, при реализации кэш-памяти L1i используется не протокол MESI, а упрощенный протокол SI. Это значит, что если обнаружены изменения, то будут сделаны многие пессимистические предположения.

Настоятельно рекомендуется всегда, когда это можно, избегать использовать самомодифицирующийся код. Память больше не является настолько дефицитным ресурсом. Лучше писать отдельные функции, а не менять одну функции в соответствие с конкретными потребностями. Может быть, однажды появится поддержка самомодифицирующегося кода, и мы сможем обнаруживать коды эксплойтов, которые пытаются подобным образом менять код. Если непременно требуется использовать самомодифицирующийся код, то для того, чтобы не создавать проблем с данными в кэш-памяти L1d, которые потребуются в кэш-памяти L1i, операции записи вообще не должны пользоваться кэш-памятью. Дополнительную информацию, касающуюся этих инструкций, смотрите в разделе 6.1.

Обычно в Linux легко распознать программы, в которых есть самомодифицирующийся код. Когда код программы создается с помощью обычных инструментальных средств, то он весь защищен от записи. Программист должен достаточно поколдовать для того, чтобы создать исполняемый файл, в котором можно выполнять запись в страницы с кодом. Когда происходит, в современных процессорах Intel x86 и x86-64 используются специализированные счетчики, подсчитывающие изменения самомодифицирующегося кода. С помощью этих счетчиков можно просто выявлять программы с самомодифицирующимся кодом даже в случае, когда из-за более слабых ограничений программа будет считаться допустимой.


Назад Оглавление Вперед