Внутренний механизм динамической загрузки DLL в C ++ в ОС? - PullRequest
2 голосов
/ 10 сентября 2009

Я не могу получить много информации о динамической загрузке DLL-файлов из C ++. Я знаю, что он использует некоторые функции, такие как LoadLibrary и FreeLibrary с GetProcAddress. Но как это работает на самом деле внутри с точки зрения ОС, например, где он на самом деле ищет файл DLL и где он загружается как память? Может ли кто-нибудь помочь мне в этом с некоторыми диаграммами?

Ответы [ 3 ]

2 голосов
/ 10 сентября 2009

Порядок поиска DLL описан в MSDN , и есть статья о загрузке DLL и статья из 100 частей *, описывающая формат PE () часть вторая здесь ) (они немного старые, но я не думаю, что они устарели). Посмотрите архивы MSDN Magazine и MSJ, и вы, вероятно, найдете больше.

0 голосов
/ 10 сентября 2009

Есть два способа использования DLL. Вы можете загрузить его динамически во время выполнения или статически связать с ним во время соединения.

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

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

Обратите внимание, что на самом деле это немного сложнее. Например, библиотеки DLL могут, в свою очередь, ссылаться на другие библиотеки DLL. Поэтому, когда загрузчик загружает DLL, прежде чем DLL можно будет считать загруженной, ему потребуется (возможно, рекурсивно) загрузить и другие DLL.

0 голосов
/ 10 сентября 2009

Для Win32 сведения о загрузчике находятся на MSDN. Смотрите здесь .

Исходя из кода C ++, вы правы (для Windows), загружаете с помощью :: LoadLibrary и разрешаете указатели на функции с помощью :: GetProcAddress. Обычно вы преобразуете результат GetProcAddress в тип, который вам известна как функция точки входа, а затем используете его в своей программе.

Например, если у вас есть архитектура подключаемого модуля, например, браузер, вы решите, какой каталог у вашего подключаемого модуля, получите список имен файлов для этого каталога, и вызовите :: LoadLibrary для каждой DLL (фильтрация имен файлов быть до вас). Для каждого из них вы должны разрешить необходимые точки входа с помощью GetProcAddress, сохранить их в структуре для этой библиотеки и поместить в какой-либо список плагинов. Позже вы будете вызывать эти указатели функций, чтобы плагин работал.

Если вы укажете относительный путь (например, «foo.dll», а не «c: \ foo.dll»), появится путь поиска в библиотеке ОС. Подробности в MSDN.

Кроме того, библиотеки DLL загружаются в адресное пространство вашего процесса. Как правило, вас не волнует, где, но в прошлом вы могли ускорить загрузку, «перебазировав» свои библиотеки DLL. Я не думаю, что есть какие-либо гарантии того, как загрузчик ОС помещает библиотеки в память, но вы всегда можете получить базовый адрес в адресном пространстве вашего процесса.

Точка входа вашей DLL (dllmain) также может отвечать на различные сообщения - присоединение потока, присоединение процесса - для разумной инициализации.

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