Крок 5 - Створення статичної бібліотеки
libc.so.6 => /lib/libc.so.6 (0x40016000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Як бачите все вірно. Програма використовує три бібліотеки:
• libc.so.6 – стандартну бібліотеку функцій мови C++.
• ld-linux.so.2 - бібліотека динамічного лінкування програм ELF формату.
• libfsdyn.so – нашу динамічну бібліотеку функцій.
Нашу бібліотеку вона знайти не може. І вірно! Динамічний лінковник шукає бібліотеки лише у відомих йому каталогах, а каталог нашої програми явно не відомий.
Для того, щоб додати нашу директорію з бібліотекою до списку відомих директорій, потрібно підредагувати файл /etc/ld.so.conf . Наприклад, у мене цей файл складається з таких рядків:
# cat /etc/ld.so.conf /usr/X11R6/lib /usr/i386-slackware-linux/lib /usr/i386-slackware-linux-gnulibc1/lib /usr/i386-slackware-linux-gnuaout/lib dron:
У всіх цих директорії зберігаються всіма використовувані бібліотеки. У цьому списку немає лише однієї директорії - /lib, яка сама по собі не потребує опису, оскільки вона є головною. Виходить, що наша бібліотека стане "помітною", якщо помістити її в один із цих каталогів, або окремо описати в окремому каталозі. Давайте для тесту опишемо, додамо рядок до кінця файлу ld.so.conf :
У мене цей файл валяється в домашньому каталогу користувача root, у Вас він може бути в іншому місці. Тепер після цього динамічний лінковник буде знати, де можна знайти наш файл, але після зміни конфігураційного файлу ld.so.conf необхідно, щоб система перечитала налаштування заново. Це робить програму ldconfig. Пробуємо запустити нашу програму:
# ./rezultdyn f1() = 25
Як бачите все запрацювало :) Якщо Ви видалите доданий нами рядок ізнову запустіть ldconfig , то дані про розташування нашої бібліотеки зникнуть і буде з'являтися та сама помилка.
Але описаний спосіб впливає всю систему загалом і вимагає доступу адміністратора системи, тобто. root. А якщо Ви простий користувач без понад можливостей?!
Для цього є інше безболісне рішення. Це використання спеціального змінного середовища LD_LIBRARY_PATH , в якому перераховуються всі каталоги, що містять власні динамічні бібліотеки. Щоб встановити цю змінну в командному середовищі bash треба набрати лише кілька команд. Для початку подивимося чи є у нас таке змінне середовище:
У мене у відповідь виводиться порожній рядок, що означає, що такого змінного середовища немає. Встановлюється вона так:
Після цього програма rezultdyn буде чудово працювати. Якщо у Вас в системі це змінне середовище вже встановлено, то, щоб не зіпсувати його значення, треба новий каталог додати до старого значення. Робиться це іншою командою:
Якщо Ви обнулите цю змінну, то бібліотека знову перестане працювати:
# export LD_LIBRARY_PATH dron:
./rezultdyn: error in loading shared libraries: libfsdyn.so: не можна Open shared object file: No such file or directory
Крок 8 - Функції роботи з динамічними бібліотеками
Якщо Ви подумали, що фокуси з динамічними бібліотеками скінчилися, то дуже помилилися. До того були квіточки, а ягідки будуть зараз :)
Виявляється, що використовувати динамічні бібліотеки можна не тільки на початку завантаження, а й у процесі роботи програми. Програма сама може викликати будь-які функції бібліотеки, коли їй захочеться. Для цього всього лише треба використовувати бібліотеку dl , яка дозволяєлінкувати бібліотеки "на льоту". Вона керує завантаженням динамічних бібліотек, викликом функцій з них та розвантаженням після кінця роботи.
Для використання функцій програмної роботи з динамічними бібліотеками необхідно підключити заголовний файл:
Щоб викликати якісь функції з динамічної бібліотеки, спочатку треба відкрити цю бібліотеку (можна сказати "завантажити"). Відкривається вона функцією:
void *dlopen (const char *filename, int flag);
Параметр filename містить шлях до бібліотеки, а параметр flag задає деякі специфічні прапори для роботи. Функція повертає покажчик на завантажену бібліотеку. У разі будь-якої помилки повертається покажчик NULL. У такому разі тест помилки зрозумілий людині можна отримати за допомогою функції dlerror(). Поки ми не замислюватимемося над цим, і я наведу стандартний код для відкриття бібліотеки:
library_handler = dlopen("/path/to/the/library.so",RTLD_LAZY); if (!library_handler)
//якщо помилка, вивести її на екран fprintf(stderr,"dlopen() error: %s\n", dlerror());
exit(1); // у разі помилки можна, наприклад, закінчити роботу програми
void * dlsym (void * handle, char * symbol);
Закривається бібліотека функцією: dlclose (void * handle);
При закритті бібліотеки динамічний лінковник перевіряє лічильник кількості відкриттів бібліотеки, і якщо вона була відкрита кількома програмами одночасно, то вона не вивантажується доти, доки всі програми не закриють цю бібліотеку.
Для прикладу створимо програму, яка як параметр отримує назву функції, яку вона використовуватиме в роботі. Наприклад, це будуть математичні функції зведення у ступінь. Створимо спочатку динамічну бібліотеку. Пишемо її код:
doublepower2(double x)
double power3(double x)< return x*x*x;
Зберігаємо його у файл lib.c та створюємо динамічну бібліотеку libpowers.so наступними командами: dron:
# gcc -fPIC -c lib.c
# gcc -shared lib.o -o libpowers.so
Тепер створюємо основну програму у файлі main.c:
/* заголовковий файл для роботи з динамічними бібліотеками */ #include
int main(int argc, char* argv[])
// хандлер зовнішньої бібліотеки
// значення для тесту
ext_library = dlopen("/root/libpowers.so",RTLD_LAZY); if (!ext_library)
//якщо помилка, вивести її на екран fprintf(stderr,"dlopen() error: %s\n", dlerror()); return 1;
//завантажуємо з бібліотеки необхідну процедуру powerfunc = dlsym(ext_library, argv[1]); value=3.0;
//виводимо результат роботи процедури printf("%s(%f) = %f\n",argv[1],value,(*powerfunc)(value));
//закриваємо бібліотеку dlclose(ext_library);
Калькулятор
Сервіс безкоштовної оцінки вартості роботи
- Заповніть заявку. Фахівці розрахують вартість вашої роботи
- Розрахунок вартості прийде на пошту та по СМС
Номер вашої заявки
Зараз на пошту прийде автоматичний лист-підтвердження з інформацією про заявку.