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

olya:~# ldd rezultdyn

libfsdyn.so => not found

libc.so.6 => /lib/libc.so.6 (0x40016000)

/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

olya:~#

Как видите все правильно. Программа использует три библиотеки:

libc.so.6 - стандартную библиотеку функций языка C++.

ld-linux.so.2 - библиотеку динамической линковки программ ELF формата.

libfsdyn.so - нашу динамическую библиотеку функций.

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

Для того, чтобы добавить нашу директорию с библиотекой в список известных директорий надо подредактировать файл /etc/ld.so.conf. Например, у меня этот файл состоит из таких строк:

olya:~# 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

olya:~#

Во всех этих директории хранятся всеми используемые библиотеки. В этом списке нет лишь одной директории - /lib, которая сама по себе не нуждается в описании, так как она является главной. Получается, что наша библиотека станет "заметной", если поместить ее в один их этих каталогов, либо отдельно описать в отдельном каталоге. Давайте для теста опишем, добавим строку в конец файла ld.so.conf:

/root

У меня этот файл находится в домашнем каталога пользователя root, у Вас он может быть в другом месте. Теперь после этого динамический линковщик будет знать где можно найти наш файл, но после изменения конфигурационного файла ld.so.conf необходимо, чтобы система перечитала настройки заново. Это делает программа ldconfig. Пробуем запустить нашу программу:

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\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\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);

};

Код главной программы готов. Требуется его откомпилировать с использованием библиотеки 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\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\n, x2=%d\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с.

Страницы: 1, 2, 3



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.