перемещение времени загрузки и виртуальной памяти - PullRequest
2 голосов
/ 25 августа 2011

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

http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries/

Также есть много статей о динамическом связывании, которые говорят об абсолютных адресах.Мое понимание неверно?

1 Ответ

9 голосов
/ 14 января 2012

Перемещение во время загрузки и поддержка виртуальной памяти - это две разные концепции. Почти все процессоры и операционные системы в наши дни поддерживают виртуальную память. Единственный действительно важный момент для понимания виртуальной памяти: забыть физические адреса. Теперь это ответственность за аппаратное обеспечение и ОС, и, если вы не пишете систему подкачки, вы можете забыть о физических адресах. Все адреса, которые использует программа, являются виртуальными. Это огромное преимущество и значительно упрощает модель программирования. В 32-битных системах это просто означает, что каждый процесс получает свое собственное пространство памяти 4 ГБ, в диапазоне от 0x00000000 до 0xffffffff.

.exe представляет процесс. Линкер создает .exe из .obj файлов. Хотя оба являются двоичными файлами, .obj файлы не являются исполняемыми, поскольку они не содержат адресов всех переменных и функций. Задача компоновщика состоит в том, чтобы предоставить эти адреса, которые он определяет, помещая эти .obj файлы в конец и затем вычисляя точные адреса всех символов (функций и переменных). Таким образом, созданный .exe содержит каждый адрес функций и переменных, «жестко запрограммированных» в нем. Но есть еще одна важная информация, необходимая для создания .exe. Линкер должен иметь инсайдерские знания о том, где в памяти будет загружен .exe. Это будет по адресу 0x00000000, или по 0xffff0000, или где-то еще? Например, в Windows все .exe всегда загружаются по абсолютному начальному адресу 0x00400000. Это называется базовым адресом. Когда компоновщик генерирует окончательные адреса символов (функций и переменных), он вычисляет их с этого адреса и далее.

Теперь .exe редко нужно загружать по любому другому адресу. Но то же самое не верно для .dll с. .ddl s такие же, как .exe s (оба отформатированы в формате файла переносимого исполняемого файла (PE), который описывает структуру памяти, например, куда идет текст, куда идут данные и как найти какой) , .dll s также имеют предпочтительный адрес. Это просто означает, что компоновщик использует это значение, когда вычисляет адреса для символов внутри .dll. Если по этому адресу загружен .dll, то мы все настроены.

Но если .dll не может быть загружен по этому адресу (скажем, это был 0x10000000), потому что какой-то другой .dll уже был загружен по этому адресу, тогда загрузчик найдет некоторое другое пространство в памяти и загрузит .dll там. Однако глобальные адреса функций и символов в .dll теперь неверны. Таким образом, загрузчик должен выполнить перемещение (также называемое «исправление»), в котором он корректирует адреса всех глобальных символов и функций, чтобы отразить их фактические адреса.

Чтобы выполнить эту настройку, загрузчик должен быть в состоянии найти все такие символы в .dll. Файл PE имеет секцию .reloc, которая содержит внутреннее смещение всех таких символов.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...