Самовыгружающийся DLL-модуль
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
Всем привет.
Задача значит у меня такая: имеется набор плагинов (каждый плагин в отдельном DLL-модуле) и в каждом реализована некая однотипная процедура. Мне нужно запускать эти процедуры в отдельных потоках.
Т.е. загрузил плагин, создал поток, запустил процедуру на выполнение, а дальше по завершении процедуры модуль сам должен выгрузиться из памяти. Во время выполнения одной процедуры может быть запущена в другом потоке процедура из другого плагина. Если эта процедура уже была запущена ранее и ещё не завершила работу, то нужно сообщить об этом пользователю...
Как мне этот механизм правильно реализовать?
Заранее благодарю...
Задача значит у меня такая: имеется набор плагинов (каждый плагин в отдельном DLL-модуле) и в каждом реализована некая однотипная процедура. Мне нужно запускать эти процедуры в отдельных потоках.
Т.е. загрузил плагин, создал поток, запустил процедуру на выполнение, а дальше по завершении процедуры модуль сам должен выгрузиться из памяти. Во время выполнения одной процедуры может быть запущена в другом потоке процедура из другого плагина. Если эта процедура уже была запущена ранее и ещё не завершила работу, то нужно сообщить об этом пользователю...
Как мне этот механизм правильно реализовать?
Заранее благодарю...
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
Рефкаунтинг.
Все кому нужны процедуры вызывают процедуру загрузки планина. Процедура смотрит, загружен ли такой плагин, и если загружен, то просто увеличивает счетчик ссылок на него. Если нет, то загружает и счетчик ставит в 1.
После того, как поток попользовался плагином, то он вызывает процедуру выгрузки плагина. А процедура сначала уменьшает счетчик ссылок, и если он стал равным 0, то выгружает.
Все кому нужны процедуры вызывают процедуру загрузки планина. Процедура смотрит, загружен ли такой плагин, и если загружен, то просто увеличивает счетчик ссылок на него. Если нет, то загружает и счетчик ставит в 1.
После того, как поток попользовался плагином, то он вызывает процедуру выгрузки плагина. А процедура сначала уменьшает счетчик ссылок, и если он стал равным 0, то выгружает.
При загрузке модуля плагина или при вызове процедуры необходимо в плагин передавать адрес CALLBACK-функции, через которую плагин будет сообщать приложению о завершении процедуры или о ходе её выполнения. Иначе приложение не будет ничего знать о текущем состоянии выполняемой процедуры.
Кроме этого потребуется реализовать менеджер загрузки-выгрузки плагинов, котоый содержал бы в себе информацию о загруженных в данный момент плагинах, а при завершении работы той или иной процедуры, выгружал бы соответствующий модуль.
Далее возможны два варианта:
1. Наиболее простой, когда плагин может выполнять одновременно лишь одну процедуру, повторное обращение к плагину в этот момент блокируется. Тогда счётчик ссылок будет лишним, поскольку у плагина будет всего два состояния: свободен или занят.
2. Когда в одном плагине может выполнятся одновременно несколько процедур. Тогда действительно необходим будет счётчик ссылок. Но и это ещё не всё, если предполагается одновременный вызов в нескольких потоках одной и той же процедуры, то здесь потребуется обеспечить её одновременную работу на несколько потоков.
Кроме этого потребуется реализовать менеджер загрузки-выгрузки плагинов, котоый содержал бы в себе информацию о загруженных в данный момент плагинах, а при завершении работы той или иной процедуры, выгружал бы соответствующий модуль.
Далее возможны два варианта:
1. Наиболее простой, когда плагин может выполнять одновременно лишь одну процедуру, повторное обращение к плагину в этот момент блокируется. Тогда счётчик ссылок будет лишним, поскольку у плагина будет всего два состояния: свободен или занят.
2. Когда в одном плагине может выполнятся одновременно несколько процедур. Тогда действительно необходим будет счётчик ссылок. Но и это ещё не всё, если предполагается одновременный вызов в нескольких потоках одной и той же процедуры, то здесь потребуется обеспечить её одновременную работу на несколько потоков.
По-моему, может я ошибаюсь, нет функции, которая выгружает длл из памяти. Все идеи хороши, но выгрузить длл нельзя, это делает система.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
LoadLibrary - загрузить
FreeLibrary - выгрузить
http://msdn.microsoft.com/en-us/library ... S.85).aspx
"Систему" тоже кто-то написал
FreeLibrary - выгрузить
http://msdn.microsoft.com/en-us/library ... S.85).aspx
"Систему" тоже кто-то написал

FreeLibrary не выгружает, он лишь уменьшает счётчик.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
Ну, собственно, точно также, как и LoadLibrary увеличивает этот же счетчик ссылок.
Вполне можно взвалить подгрузку и выгрузку плагинов на OC. Если нужно запустить функцию из плагина, делается LoadLibrary, а потом FreeLibrary.
Если другой поток параллельно сделает то же самое, то все будет пучком.
Т.е. в принципе, относительно данной темы:The system maintains a per-process reference count on all loaded modules. Calling LoadLibrary increments the reference count. Calling the FreeLibrary or FreeLibraryAndExitThread function decrements the reference count. The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count).
Вполне можно взвалить подгрузку и выгрузку плагинов на OC. Если нужно запустить функцию из плагина, делается LoadLibrary, а потом FreeLibrary.
Если другой поток параллельно сделает то же самое, то все будет пучком.

Naeel Maqsudov Он хотел именно выгрузить из памяти, а ты показал как уменьшить счётчик, а не как выгрузить:
сам должен выгрузиться из памяти.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
#define while if
Оптимизация по размеру:
#define struct union
А разве возможно будет выгрузить DLL из памяти, если кто-то еще продолжает ее использовать?Airhand писал(а):Naeel Maqsudov Он хотел именно выгрузить из памяти, а ты показал как уменьшить счётчик, а не как выгрузить:
В какой именно момент система физически выгрузит модуль из памяти для нас не столь важно, главное произвести "логическую" отстыковку DLL-модуля от приложения. А для этого нужно чтобы количество вызовов FreeLibrary() соответствовало количеству ранее вызванных LoadLibrary(). Понятно, что какое-то время модуль ещё побудет в памяти, чтобы при повторном обращении к нему системе не пришлось бы его снова грузить с диска. Но это уже внутрисистемные механизмы кэширования и нас они мало интересуют. Здесь наиболее важен сам момент вызова функции FreeLibrary() для многопоточного приложения.
Предлагаю на выбор два варианта:
1. Процедура, которая выполняется внутри плагина, сама при завершении вызывает FreeLibrary() для своего модуля, и тогда модуль в прямом смысле становится как бы самовыгружаемым.
2. Процедура через CALLBACK-функцию сообщает о своём завершении плагин-мэнеджеру, и он уже сам выгружает соответствующий модуль.
Второй способ более безопасный.
Предлагаю на выбор два варианта:
1. Процедура, которая выполняется внутри плагина, сама при завершении вызывает FreeLibrary() для своего модуля, и тогда модуль в прямом смысле становится как бы самовыгружаемым.
2. Процедура через CALLBACK-функцию сообщает о своём завершении плагин-мэнеджеру, и он уже сам выгружает соответствующий модуль.
Второй способ более безопасный.