Смекни!
smekni.com

Разработка статических и динамических библиотек на языке программирования С/C++ в операционных системах UNIX (стр. 3 из 3)

olya:~# ldconfig

olya:~# ./rezultdyn

f1() = 25

f2() = 10

olya:~#

Как видите все заработало. Если теперь удалить добавленную нами строку и снова запустите ldconfig, то данные о расположении нашей библиотеки исчезнут и будет появляться таже самая ошибка.

Но описанный метод влияет на всю систему в целом и требует доступа администратора системы, т.е. root. А если Вы простой пользователь без сверх возможностей ?!

Для такого случая есть другое безболезненное решение. Это использование специальной переменной среды LD_LIBRARY_PATH, в которой перечисляются все каталоги содержащие пользовательские динамические библиотеки. Для того, чтобы установить эту переменную в командной среде bash надо набрать всего несколько команд. Для начала посмотрим есть ли у нас такая переменная среды:

olya:~# echo $LD_LIBRARY_PATH

У меня в ответ выводится пустая строка, означающая, что такой переменной среды нет. Устанавливается она следующим образом:

olya:~# LD_LIBRARY_PATH=/root

olya:~# export LD_LIBRARY_PATH

После этого программа rezultdyn будет прекрасно работать. В случае, если в системе эта переменная среды уже уставновлена, то, чтобы не испортить ее значение, надо новый каталог прибавить к старому значению. Делается это другой командой:

olya:~# LD_LIBRARY_PATH=/root:${LD_LIBRARY_PATH}

olya:~# export LD_LIBRARY_PATH

Если обнулить эту переменную, то снова библиотека перестанет работать:

olya:~# LD_LIBRARY_PATH=""

olya:~# export LD_LIBRARY_PATH

olya:~# ./rezultdyn

./rezultdyn: error in loading shared libraries: libfsdyn.so: cannot open

shared object file: No such file or directory

olya:~#

Также параллельно можно зайти в систему под другим пользователем или даже тем же самым, но если просмотреть значение LD_LIBRARY_PATH, то увидим ее прежнее значение. Это означает, что два разных пользователя Linux не могут влиять на работу друг друга, а это и есть самое главное хорошее отличие систем Unix от большинства других систем.


4 Создание динамических библиотек

4.1 Функции работы с динамическими библиотеками

Оказывается, что использовать динамические библиотеки можно не только в начале загрузки, но и в процессе самой работы программы. Программа сама может вызывать любые функции из библиотеки, когда ей захочется. Для этого всего-лишь надо использовать библиотеку dl, которая позволяет линковать библиотеки "на лету". Она управляет загрузкой динамических библиотек, вызовом функций из них и выгрузкой после конца работы.

Для использования функций программной работы с динамическими библиотеками необходимо подключить заголовочный файл:

#include <dlfcn.h>

Чтобы вызывать какие-то функции из динамической библиотеки сначала надо открыть эту библиотеку (можно сказать "загрузить"). Открывается она функцией:

void *dlopen (const char *filename, int flag);

Параметр filename содержит путь до требуемой библиотеки, а параметр flag задает некоторые специфические флаги для работы. Функция возвращает указатель на загруженную библиотеку. В случае любой ошибки возвращается указатель NULL. В таком случае тест ошибки понятный человеку можно получить с помощью функции dlerror(). Пока мы не будем задумываться над этим, и я приведу стандартный код для открытия библиотеки:

void *library_handler;

//......

//загрузка библиотеки

library_handler = dlopen("/path/to/the/library.so",RTLD_LAZY);

if (!library_handler){

//если ошибка, то вывести ее на экран

fprintf(stderr,"dlopen() error: %s&bsol;n", dlerror());

exit(1); // в случае ошибки можно, например, закончить работу программы

};

После этого можно работать с библиотекой. А работа эта заключается в получении адреса требуемой функции из библиотеки. Получить адрес функции или переменной можно по ее имени с помощью функции:

void *dlsym(void *handle, char *symbol);

Для этой функции требуется адрес загруженной библиотеки handle, полученный при открытии функцией dlopen(). Требуемая функция или переменная задается своим именем в переменной symbol.

Закрывается библиотека функцией:

dlclose(void *handle);

При закрытии библиотеки динамический линковщик проверяет счетчик количества открытий библиотеки, и если она была открыта несколькими программами одновременно, то она не выгружается до тех пор, пока все программы не закроют эту библиотеку.

Для примера создадим программу, которая в качестве параметра получает название функции, которую она будет использовать в работе. Например, это будут математические функции возведения в степень. Создадим сначала динамическую библиотеку. Пишем ее код:

double power2(double x){

return x*x;

};

double power3(double x){

return x*x*x;

};

double power4(double x){

return power2(x)*power2(x);

};

//......

Сохраняем его в файл lib.c и создаем динамическую библиотеку libpowers.so следующими командами:

olya:~# gcc -fPIC -c lib.c

olya:~# gcc -shared lib.o -o libpowers.so

Теперь создаем основную программу в файле main.c:

#include <stdio.h>

/* заголовочный файл для работы с динамическими библиотеками */

#include <dlfcn.h>

int main(int argc, char* argv[]){

void *ext_library;// хандлер внешней библиотеки

double value=0;// значение для теста

double (*powerfunc)(double x);// переменная для хранения адреса функции

//загрузка библиотеки

ext_library = dlopen("/root/libpowers.so",RTLD_LAZY);

if (!ext_library){

//если ошибка, то вывести ее на экран

fprintf(stderr,"dlopen() error: %s&bsol;n", dlerror());

return 1;

};

//загружаем из библиотеки требуемую процедуру

powerfunc = dlsym(ext_library, argv[1]);

value=3.0;

//выводим результат работы процедуры

printf("%s(%f) = %f&bsol;n",argv[1],value,(*powerfunc)(value));

//закрываем библиотеку

dlclose(ext_library);

};

Код главной программы готов. Требуется его откомпилировать с использованием библиотеки dl:

olya:~# gcc main.c -o main -ldl

Получим программный файл main, который можно тестировать. Наша программа должна возводить значение 3.0 в требуемую нами степень, которая задается названием функции. Давайте попробуем:

olya:~# ./main power2

power2(3.000000) = 9.000000

olya:~# ./main power3

power3(3.000000) = 27.000000

olya:~# ./main power4

power4(3.000000) = 81.000000

olya:~#

Мы используем функции, зная лишь их название. Представьте открывающиеся возможности для программ, на основе этого метода можно создавать плагины для программ, модернизировать какие-то части, добавлять новые возможности и многое другое.

4.2 Создание динамической библиотеки для решения системы линейных уравнений

В качестве примера использования динамических библиотек напишем программу для решения системы линейных уравнений.

Пусть система имеет вид:

a11*x1+a12*x2=b1;

a21*x1+a22*x2=b2;

Решение этой системы находим через обратную матрицу A-1.

A*X=B

X=A-1*B

;
;
;

;

Программа в качестве параметров принимает значение коефициентов системы и название функции, которую она использует.

Создадим динамическую библиотеку:

Так как функция возвращает два результата x1 и x2 в программе будем использовать структуру.

"mytype.h" :

struct DPair {

double first;

double second;

};

Struct DPair (*powerfunc)(double,double,double,double,double,double);

"libsysur.c" :

#include "mytype.h"

struct DPair sys2(double a11, double a12,double a21, double a22,double b1, double b2){

//nahodim opredelitel sistemy

struct DPair dPair;

double opr=a11*a22-a12*a21;

if (opr!=0) {

double ao11=a22; double ao12=-a21;

double ao21=-a12; double ao22=a11;

dPair.first=(ao11*b1+ao21*b2)/opr;

dPair.second=(ao12*b1+ao22*b2)/opr;

}

return dPair;

}

Создаем динамическую библиотеку libsysur.so следующими командами:

bash-3.00# gcc -fPIC -c libsysur.c

bash-3.00# gcc -shared libsysur.o -o libsysur.so

Создаем основную программу:

"sysur.c" :

#include <stdio.h>

#include <dlfcn.h>

#include "mytype.h"

int main(int argc, char* argv[]){

void *ext_library; //хандлер внешней функции

double a11;double a12; double a21; double a22;

double b1; double b2;

double (*powerfunc)(double a11,double a12, double a21, double a22,double b1, double b2);//переменная, для хранения адреса функции

//загрузка библиотеки

ext_library=dlopen("/root/dynamik/libsysur.so",RTLD_LAZY);

if (!ext_library){

//если ошибка, вывести на экран

fprintf(stderr,"dlopen() error: %s&bsol;n", dlerror());

return 1;

};

//загружаем из библиотеки требуемую процедуру

powerfunc=dlsym(ext_library, argv[1]); //получаем адрес требуемой функции

//ext_library-адрес загруженной библ.

//argv-требуемая функция или переменная

printf("Vvedite a11 a12 :");

scanf("%lf %lf",&a11,&a12);

printf("Vvedite a21 a22 :");

scanf("%lf %lf",&a21,&a22);

printf("Vvedite b1, b2 :");

scanf("%lf %lf",&b1,&b2);

struct DPair sq=(*powerfunc)(a11,a12,a21,a22,b1,b2);

printf("x1=%lf&bsol;n, x2=%d&bsol;lf",sq.first,sq.second);

//выводим результат работы процедуры

//закрываем библиотеку

dlclose(ext_library);

};

Компилируем код главной программы:

bash -3.00# gcc sysur.c -o sysur -ldl

Выводы

В курсовой работе были рассмотрены рассмотрены вопросы разработки статических и динамических библиотек на языке программирования С/C++ в операционных системах UNIX.

Использование библиотеки позволяет компактно хранить все требуемые объектные файлы в одном месте, и при этом значительно повысить скорость компиляции.

Объектные библиотеки по способу использования разделяются на статические и динамические библиотеки

Статическая библиотека - это коллекция объектных файлов, которые присоединяются к программе во время линковки программы. В работе самой программы статические библиотеки они не принимают участие, в отличие от динамических библиотек.

В динамической библиотеке объектные файлы из библиотеки не присоединяются к программе. Присоединение этих объектных файлов осуществляет системный динамический загрузчик во время запуска программы. Загрузчик проверяет все библиотеки прилинкованные с программе на наличие требуемых объектных файлов, затем загружает их в память и присоединяет их в копии запущенной программы, находящейся в памяти.

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


Список использований литературы

1. http://club.shelek.com/

2. http://helpsite.narod.ru/

3. http://myforum.net.ua/index.php?

4. http://ishodniki.ru/

5. Робин Бурк и др. Unix для системных администраторов.Энциклопедия пользователя. - Киев 1998. - 864с.