Интересуют возможности по загрузке/выгрузке динамических библиотек во время выполнения.
У сервера есть подключаемые службы. Каждая служба в своей динамической библиотеке. При работе во время выполнения загружаются необходимые библиотеки, создаются объекты служб (по одному на библиотеку). В библиотеках есть синглтоны (общие данные), от них не избавиться.
Хочется иметь возможность на лету заменять функциональность библиотек. Т.е. отправлять на сервер новую версию библиотеки и делать "подмену". Но тут есть два варианта.
1. Сначала полностью выгружать старую версию, потом загружать новую.
2. Сначала загружать новую, делать "быструю подмену", потом выгружать старую.
Второй вариант естественно намного более предпочтителен, т.к. имеет намного меньшую задержку в работе.
Я ещё не пробовал, интересно будет ли работать. Я предполагаю, что первый вариант работать будет, а вот со вторым возникнут проблемы из-за общих данных.
Также хочется загрузить два объекта одной и той-же службы, но чтобы общие данные у каждой службы били свои. Тут что-нибудь можно сделать? Может можно загрузить две библиотеки? Делать можно всё что угодно, вносить изменения в код, переименовывать файлы библиотек и т.п.
Если есть литература, буду благодарен.
Помогите разобраться с динамическими библиотеками (загрузка/выгрузка во время выполнения)
Модератор: Модераторы разделов
-
RasenHerz
- Сообщения: 1341
- ОС: Arch Linux amd64
Re: Помогите разобраться с динамическими библиотеками
если я правильно вас понял, то вы хотите реализовать что-то вроде плагинов.
скажу как когда-то делал я, реализуя программу которая могла скачивать файлы по разным протоколам, где каждый протокол был релизован в виде плагина(который является динамической библиотекой).
что я сделал:
1) Изучил файл <dlfcn.h>. понял что-такое dlopen(), dlsym(), dlclose() - для базовой функциональности этого хватит.
2) Продумал интерфейс плагина и решил что, во-первых, от каждого плагина требуются функции инициализации(в каждом плагине она должна называтся одинаково), соединения с сервером, получения размера файла, самого файла, ну и конечно разрыва соединения с сервером; во-вторых, все функции плагина должны быть легко доступны приложению, поэтому я решил создать стуктуру, поля которой будут хранить адреса необходимых функций, структура создается в главном приложении и передается в функцию инициализирующую плагин.
3) Набросал простенький плагин:
4) написал код клиента:
вот вроде и все.
что касается вашего вопроса насчет выгрузки библиотек и подмены функций, то дело, как говорится, хозяйское - можете сначала выгружать старую библиотеку, а потом загружать новую, а можно и наоборот.
делать "подмену" тоже просто - загружаете новую библиотеку и заменяете в старой структуре (от старой библиотеки) необходимые поля.
скажу как когда-то делал я, реализуя программу которая могла скачивать файлы по разным протоколам, где каждый протокол был релизован в виде плагина(который является динамической библиотекой).
что я сделал:
1) Изучил файл <dlfcn.h>. понял что-такое dlopen(), dlsym(), dlclose() - для базовой функциональности этого хватит.
2) Продумал интерфейс плагина и решил что, во-первых, от каждого плагина требуются функции инициализации(в каждом плагине она должна называтся одинаково), соединения с сервером, получения размера файла, самого файла, ну и конечно разрыва соединения с сервером; во-вторых, все функции плагина должны быть легко доступны приложению, поэтому я решил создать стуктуру, поля которой будут хранить адреса необходимых функций, структура создается в главном приложении и передается в функцию инициализирующую плагин.
3) Набросал простенький плагин:
Код: Выделить всё
#include "ftp.h"
#include <stdio.h>
FTP *ftpserv;
int logged = 0;
extern "C" int init_plugin(PLUGIN *plugin){
if (!plugin) return 0;
printf("Invoking ftp_init_plugin()\n");
ftpserv = new FTP();
int ret = (ftpserv) ? 1 : 0;
plugin->connect = ftp_connect;
plugin->get_size = ftp_get_size;
/* и так далее */
return ret;
}
extern "C" int ftp_connect(char *server){
printf("Invoking ftp_connect(%s)\n", server);
if(ftpserv->connect_to(server)){
if (ftpserv->anon_login()){
ftpserv->PASV();
logged = 1;
return logged;
}
else
return 0;
}
else
return 0;
}
extern "C" int ftp_get_size(char *file){
printf("Invoking ftp_get_size(%s)\n", file);
if (!logged)
return 0;
return (ftpserv->SIZE(file));
}4) написал код клиента:
Код: Выделить всё
int main(int argc, char** argv) {
HANDLE ftp_handle = 0;
ftp_handle = dlopen("./libftp.so", RTLD_LAZY); /* открываем динамическую библиотеку */
if (!ftp_handle){
perror("dl");
dlclose(ftp_handle);
return (EXIT_FAILURE);
}
PLUGIN *pl = new PLUGIN;
INIT_PLUGIN init = 0; /* указатель на функцию */
init = (INIT_PLUGIN)dlsym(ftp_handle, INIT_FUNC_NAME); /* ищем функцию в библиотеке */
if (!init){
perror("dl");
dlclose(ftp_handle);
return (EXIT_FAILURE);
}
init(pl);
pl->connect("127.0.0.1");
/* и другие вызовы */
return (EXIT_SUCCESS);
}вот вроде и все.
что касается вашего вопроса насчет выгрузки библиотек и подмены функций, то дело, как говорится, хозяйское - можете сначала выгружать старую библиотеку, а потом загружать новую, а можно и наоборот.
делать "подмену" тоже просто - загружаете новую библиотеку и заменяете в старой структуре (от старой библиотеки) необходимые поля.
-
theven
- Сообщения: 5
- ОС: Gentoo
Re: Помогите разобраться с динамическими библиотеками
Загрузчик делает чтобы в памяти всегда находилась только одна копия библиотеки и не загружает её повторно. На что он смотрит при загрузке? Что нужно сделать с библиотекой чтобы он решил что это уже другая библиотека?
-
Portnov
- Модератор
- Сообщения: 1786
- Статус: Матёрый линуксоид
- ОС: Debian testing/unstable
Re: Помогите разобраться с динамическими библиотеками
Подозреваю, что сменить soname. Но не уверен.
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
-
RasenHerz
- Сообщения: 1341
- ОС: Arch Linux amd64
Re: Помогите разобраться с динамическими библиотеками
попробую сегодня покопаться с этим, может чего найду. а нельзя ли добавлять к билиотекам какое-нибудь расширение, к примеру, указывающее ее версию? что-то вроде libftp.so.0.0.1
-
theven
- Сообщения: 5
- ОС: Gentoo
Re: Помогите разобраться с динамическими библиотеками
Ещё проблема в том что в библиотеках есть общие данные (статические члены), и даже если библиотеку переименовать он всё равно использует одни и те-же данные. Что с функциональностью происходит я вообще чего-то запутался. Поэтому и прошу помощи, не понимаю я как это дело работает.