Самовыгружающийся DLL-модуль

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Decoder
Сообщения: 308
Зарегистрирован: 19 фев 2008, 23:11
Откуда: Moscow

Всем привет.
Задача значит у меня такая: имеется набор плагинов (каждый плагин в отдельном DLL-модуле) и в каждом реализована некая однотипная процедура. Мне нужно запускать эти процедуры в отдельных потоках.
Т.е. загрузил плагин, создал поток, запустил процедуру на выполнение, а дальше по завершении процедуры модуль сам должен выгрузиться из памяти. Во время выполнения одной процедуры может быть запущена в другом потоке процедура из другого плагина. Если эта процедура уже была запущена ранее и ещё не завершила работу, то нужно сообщить об этом пользователю...

Как мне этот механизм правильно реализовать?
Заранее благодарю...
Аватара пользователя
Naeel Maqsudov
Сообщения: 2570
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

Рефкаунтинг.

Все кому нужны процедуры вызывают процедуру загрузки планина. Процедура смотрит, загружен ли такой плагин, и если загружен, то просто увеличивает счетчик ссылок на него. Если нет, то загружает и счетчик ставит в 1.

После того, как поток попользовался плагином, то он вызывает процедуру выгрузки плагина. А процедура сначала уменьшает счетчик ссылок, и если он стал равным 0, то выгружает.
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

При загрузке модуля плагина или при вызове процедуры необходимо в плагин передавать адрес CALLBACK-функции, через которую плагин будет сообщать приложению о завершении процедуры или о ходе её выполнения. Иначе приложение не будет ничего знать о текущем состоянии выполняемой процедуры.
Кроме этого потребуется реализовать менеджер загрузки-выгрузки плагинов, котоый содержал бы в себе информацию о загруженных в данный момент плагинах, а при завершении работы той или иной процедуры, выгружал бы соответствующий модуль.
Далее возможны два варианта:
1. Наиболее простой, когда плагин может выполнять одновременно лишь одну процедуру, повторное обращение к плагину в этот момент блокируется. Тогда счётчик ссылок будет лишним, поскольку у плагина будет всего два состояния: свободен или занят.
2. Когда в одном плагине может выполнятся одновременно несколько процедур. Тогда действительно необходим будет счётчик ссылок. Но и это ещё не всё, если предполагается одновременный вызов в нескольких потоках одной и той же процедуры, то здесь потребуется обеспечить её одновременную работу на несколько потоков.
Аватара пользователя
Airhand
Сообщения: 239
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

По-моему, может я ошибаюсь, нет функции, которая выгружает длл из памяти. Все идеи хороши, но выгрузить длл нельзя, это делает система.
Оптимизация по скорости:
#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

"Систему" тоже кто-то написал ;)
Аватара пользователя
Airhand
Сообщения: 239
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

FreeLibrary не выгружает, он лишь уменьшает счётчик.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
Аватара пользователя
Naeel Maqsudov
Сообщения: 2570
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

Ну, собственно, точно также, как и LoadLibrary увеличивает этот же счетчик ссылок.
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.
Если другой поток параллельно сделает то же самое, то все будет пучком. :)
Аватара пользователя
Airhand
Сообщения: 239
Зарегистрирован: 06 окт 2005, 16:21
Откуда: Dnepropetrovsk

Naeel Maqsudov Он хотел именно выгрузить из памяти, а ты показал как уменьшить счётчик, а не как выгрузить:
сам должен выгрузиться из памяти.
Оптимизация по скорости:
#define while if
Оптимизация по размеру:
#define struct union
BBB
Сообщения: 1298
Зарегистрирован: 27 дек 2005, 13:37

Airhand писал(а):Naeel Maqsudov Он хотел именно выгрузить из памяти, а ты показал как уменьшить счётчик, а не как выгрузить:
А разве возможно будет выгрузить DLL из памяти, если кто-то еще продолжает ее использовать?
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

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

Второй способ более безопасный.
Ответить