в чем разница между ссылками и загрузкой на языке c - PullRequest
14 голосов
/ 23 декабря 2009

Связывание и загрузка динамических библиотек происходят во время выполнения? или во время выполнения происходит только загрузка библиотеки?

Ответы [ 7 ]

18 голосов
/ 23 декабря 2009

См. Ранее очень хорошее замечание о различии между статическим и динамическим связыванием. Предполагая, что вы имеете в виду динамическое связывание, тогда:

Как загрузка, так и (динамическая) компоновка выполняются компоновщиком - в linux и других Unix-подобных системах это делается с помощью /lib/ld.so, которая является реальной программой, запускаемой операционной системой практически во всех случаях. ld.so в свою очередь загружает ваше приложение - mygameBinary в память, а ld.so затем читает из файла mygameBinary список динамически связанных библиотек, которые ему требуются.

Затем компоновщик ld.so загружает каждую из этих библиотек в память по очереди, например, libc.so, libpthread.so, libopengl.so и рассматривает то, что могут потребоваться другим библиотекам для этих , например, libm.so.

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

Как только эта связь будет завершена, приложение запускается, вызывая функцию _start в mygameBinary, которая затем вызывает main, и ваша игра запускается.

Динамическое связывание таким образом необходимо для поддержки следующего:

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

Некоторые ОС различаются по деталям, например, OSX и AIX предварительно загружают определенный набор библиотек в фиксированные места в памяти. Это означает, что их не нужно загружать, просто связывать, что может быть быстрее.

Некоторые ОС, такие как OSX, а иногда и Linux, поддерживают предварительную связь, которая представляет собой процесс, при котором скрипт запускает приложения в вашей системе перед их запуском и выполняет связывание. Когда вы запускаете их, вам не нужно связывать их. Это важно, потому что связывание занимает значительную часть времени вашего компьютера при запуске приложения, и некоторые приложения могут запускаться несколько раз в секунду, например gcc, cpp и as во время процесса создания приложения или фильтрации сценарии при индексации данных вашего компьютера (OSX Spotlight).

6 голосов
/ 23 декабря 2009

Связывание - это процесс, при котором некоторые небольшие исполняемые файлы объединяются в один большой исполняемый файл.

Загрузка - загрузка исполняемого файла в память перед выполнением.

3 голосов
/ 23 декабря 2009

Существует два типа связывания: статическое связывание и динамическое связывание.

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

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

1 голос
/ 23 декабря 2009

file01.c, file02.c -> продуцирует -> file01.o, file02.o -> Эти данные .o объединяются и помещаются в одну динамическую библиотеку, то есть lib1.a file11.c, file12.c -> производит -> файл11.o, файл12.o -> Эти данные .o забиты и помещены в одну динамическую библиотеку, то есть lib2.a

Теперь у меня есть 2 библиотеки, которые, наконец, связаны друг с другом для создания исполняемого файла (например, .elf или .mot или .fls). Этот процесс связывания информации из lib1.a и lib2.a в единый исполняемый файл называется связыванием.

Теперь мне нужно загрузить это в память, чтобы запустить его, чтобы увидеть поведение окончательного исполняемого файла. Процесс загрузки конечного исполняемого файла (например, .elf или .mot или .fls) в память для запуска, который называется загрузкой.

Надеюсь, это прояснит важность связывания и загрузки (однако определения не подходят: -)).

1 голос
/ 23 декабря 2009

Оба происходят во время выполнения для динамических библиотек.

Сначала загружаются библиотеки вместе со всеми их зависимостями (и зависимостями этих библиотек и т. Д.). Затем динамический компоновщик разрешает символы в загруженных библиотеках. Обычно обе эти функции реализуются одним и тем же программным обеспечением; в Linux это ld.so .

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

Подробное описание того, как это происходит, как хэшируются имена, как дорого обходятся символы во время выполнения и т. Д., Как писать общие библиотеки .

0 голосов
/ 23 декабря 2009

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

0 голосов
/ 23 декабря 2009

Системы Windows и Unix используют совершенно разные подходы к динамическим библиотекам.

Windows DLL не связаны. Следовательно, вы не можете делиться статическими объектами между DLL. Это как отдельная программа в вашем адресном пространстве.

Общие объекты Unix действительно «связаны» во время выполнения, так же как разные модули одного проекта, выполняющие разрешение символов.

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