ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Динамическое связывание во время выполнения

Начало тут:
1. динамически подключаемые библиотеки;
2. о динамически подключаемых библиотеках подробнее;
3. преимущества динамического связывания;
4. создание динамически подключаемой библиотеки;
5. функция точки входа DLL;
6. динамическое связывание во время запуска.

Перевод с английского статьи от 31.05.2018 г. «Run-Time Dynamic Linking»:
https://docs.microsoft.com/ru-ru/windows/win32/dlls/run-time-dynamic-linking
(На данный момент на этом сайте нет перевода этой статьи на русский, есть только версия на английском.)

Когда приложение вызывает функцию LoadLibrary или LoadLibraryEx, [операционная] система пытается найти DLL (подробнее об этом читайте в статье «Порядок поиска динамически подключаемой библиотеки»). Если поиск увенчался успехом, система отображает модуль DLL в виртуальное адресное пространство процесса и увеличивает на единицу счетчик ссылок [на эту DLL]. Если вызов функции LoadLibrary или LoadLibraryEx определяет DLL, чей код уже отображен в виртуальное адресное пространство вызывающего процесса, эта функция просто возвращает дескриптор этой DLL и увеличивает на единицу счетчик ссылок на эту DLL. Отметим, что две библиотеки DLL, имеющие одно и то же название и расширение файла, но находящиеся в разных каталогах, не считаются одной и той же DLL.

Система вызывает функцию точки входа в контексте потока выполнения, который вызвал функцию LoadLibrary или LoadLibraryEx. Функция точки входа не вызывается, если DLL уже была загружена процессом посредством вызова функции LoadLibrary или LoadLibraryEx, но при этом не было соответствующего вызова функции FreeLibrary.

Если система не может найти DLL или если функция точки входа возвратила значение FALSE, то функция LoadLibrary или LoadLibraryEx возвращает значение NULL. Если функция LoadLibrary или LoadLibraryEx отрабатывает успешно, она возвращает дескриптор модуля DLL. Процесс может использовать этот дескриптор, чтобы указать на эту DLL в обращении к функциям GetProcAddress, FreeLibrary или FreeLibraryAndExitThread.

Функция GetModuleHandle возвращает дескриптор, который может использоваться в функциях GetProcAddress, FreeLibrary или FreeLibraryAndExitThread. Функция GetModuleHandle отработает успешно, только если модуль DLL уже отображен в адресное пространство процесса с помощью динамического связывания во время запуска программы или с помощью предыдущего вызова функции LoadLibrary или LoadLibraryEx. В отличие от функции LoadLibrary или LoadLibraryEx функция GetModuleHandle не увеличивает на единицу счетчик ссылок на модуль. Функция GetModuleFileName получает полный путь к модулю, связанному с дескриптором, который возвращают функции GetModuleHandle, LoadLibrary или LoadLibraryEx.

Процесс может использовать функцию GetProcAddress, чтобы получить адрес экспортируемой функции DLL с помощью дескриптора модуля DLL, возвращенного одной из функций LoadLibrary или LoadLibraryEx, GetModuleHandle.

Когда необходимость в модуле DLL отпадает, процесс может вызвать функцию FreeLibrary или функцию FreeLibraryAndExitThread. Эти функции уменьшают на единицу счетчик ссылок на модуль и выгружают код DLL из виртуального адресного пространства процесса, если счетчик ссылок становится равен нулю.

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

Динамическое связывание во время выполнения программы может послужить причиной проблем, если DLL использует функцию DllMain, чтобы выполнить инициализацию для каждого потока выполнения процесса, из-за того, что функция точки входа не вызывалась для потоков выполнения, существовавших перед вызовом функции LoadLibrary или LoadLibraryEx. Чтобы увидеть пример, показывающий, как справиться с этой проблемой, читайте статью «Использование локального хранилища потока в динамически подключаемой библиотеке».
Tags: Английский язык, Образование, Программирование
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments