2016-03-18 2 views
3

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

ответ

4

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

Это не относится к библиотекам: библиотеки не могут знать, какой диапазон адресов будет бесплатным в любом процессе, который хочет его загрузить, поэтому он должен использовать position-independent code.

OS X также требует PIC для исполняемых файлов. Почему я никогда не искал; возможно, они хотят иметь возможность делать ASLR.

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

4

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

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

Вы можете иметь глобальную переменную типа:

int x ; 

и ссылаться на него

main() 
{ 
    int y = x + 1 ; 
} 

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

подобные вещи вызывают проблемы с относительной адресацией во время компоновки:

static int *x = &y ; 

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

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

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

Смежные вопросы