Розробка статичних і динамічних бібліотек на мові програмування С C в операційних системах

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Зміст
Введення
1 Компіляція програм мовою C / C + +
2 Компіляція декількох файлів
3 Створення бібліотек об'єктних файлів
3.1 Бібліотеки об'єктних файлів
3.2 Створення статичної бібліотеки
3.3 Створення динамічної бібліотеки
3.4 Використання динамічних бібліотек
4 Створення динамічних бібліотек
4.1 Функції роботи з динамічними бібліотеками
4.2 Створення динамічної бібліотеки для вирішення системи лінійних рівнянь
Висновки
Список використаної літератури

Введення
Прості програми звичайно складаються з одного вихідного файлу. Але якщо програми стає великою, її рекомендується їх розбивати на шматки, які функціонально обмежені і закінчені. Так як процес виправлення при великому вихідному тексті стає складним і пошук невеликий помилки може спричинити за собою вимушене "вивчення" коду заново. Також великий файл програми збільшує час компіляції.
Але якщо кожна функція буде міститися в окремому файлі, то таких файлів може виявитися десятки або навіть сотні. Управляти такою кількістю файлів дуже складно. Для цього був придуманий механізм створення бібліотек об'єктних файлів.
Бібліотека об'єктних файлів - це файл, що містить кілька об'єктних файлів, які будуть використовуватися разом у стадії компонування програми. Бібліотека містить символьний індекс, який складається з назв функцій і змінних і т.д., які містяться в бібліотеці. Це дозволяє прискорити процес компонування програми, тому що пошук функцій і змінних в об'єктних файлах бібліотеки відбувається набагато швидше, ніж пошук в наборі зазначених об'єктних файлів.
Тому використання бібліотеки дозволяє компактно зберігати всі необхідні об'єктні файли в одному місці, і при цьому значно підвищити швидкість компіляції.
У курсовій роботі наведені приклади створення та використання статичних і динамічних бібліотек. Д розроблено кілька простих динамічних бібліотек (зведення числа у ступінь і рішення системи лінійних рівнянь)

1 Компіляція програм мовою C / C + +
Компілятор перетворює код програми на "людському" мові в об'єктний код зрозумілий комп'ютера. Компіляторів під Linux існує багато, практично для кожного поширеного мови. Більшість самих затребуваних компіляторів входить в набір GNU Compiler Collection, відомих під назвою GCC (http://gcc.gnu.org/).
Спочатку абревіатура GCC мала сенс GNU C Compiler, але у квітні 1999 року співтовариство GNU вирішило взяти на себе більш складну місію і почати створення компіляторів для нових мов з новими методами оптимізації, підтримкою нових платформ, поліпшених runtime-бібліотек та інших змін (http:/ / gcc.gnu.org / gccmission.html). Тому сьогодні колекція містить в собі компілятори для мов C, C + +, Objective C, Chill, Fortran, Ada і Java, як бібліотеки для цих мов (libstdc + +, libgcj, ...).
Компіляція програм здійснюється командою:
gcc <ім'я файлу>
Після цього, якщо процес компіляції пройде успішно, то ви отримаєте завантаження a.out, запустити який можна командою:
. / A.out
Для прикладу давайте напишемо маленьку найпростішу програмку:
# Include <stdio.h>
int main () {
printf ("[http://linux.firststeps.ru] \ n");
printf ("Our first program for Linux. \ n");
return 0;
};

2 Компіляція декількох файлів
Зазвичай прості програми складаються з одного вихідного файлу. Справа йде трохи складніше, якщо ця програма стає великою. При роботі з такою програмою може виникнути кілька досить серйозних проблем:
Файл, стаючи більшим, збільшує час компіляції, і найменші зміни в початковому тексті автоматично змушують витрачати час програміста на перекомпіляцію програми.
Якщо над програмою працює багато людей, то практично неможливо відстежити зроблені зміни.
Процес правки і саме орієнтування при великому вихідному тексті стає складним і пошук невеликий помилки може спричинити за собою вимушене "вивчення" коду заново.
Це далеко не всі пробеми, які можуть виникнути при наявності програми "монстра". Тому при розробці програм рекомендується їх розбивати на шматки, які функціонально обмежені і закінчені. У цьому значно допомагає сама мова C + +, надаючи свій багатий синтаксис.
Для того, щоб винести функцію або змінну в окремий файл треба перед нею поставити зарезервоване слово extern. Для прикладу створимо програму з декількох файлів. Спочатку створимо головну програму, в якій будуть дві зовнішні процедури. Назвемо цей файл main.c:
# Include <stdio.h>
/ / Описуємо функцію f1 () як зовнішню
extern int f1 ();
/ / Описуємо функцію f2 () як зовнішню
extern int f2 ();
int main ()
{
int n1, n2;
n1 = f1 ();
n2 = f2 ();
printf ("f1 () =% d \ n", n1);
printf ("f2 () =% d \ n", n2);
return 0;
}
Тепер створюємо два файли, кожен з яких буде містити повне визначення зовнішньої функції з головної програми. Файли назвемо f1.c і f2.c:
/ / Файл f1.c
int f1 ()
{
return 2;
}
/ / Файл f2.c
int f2 ()
{
return 10;
}
Після цього процес компіляції програми за допомогою gcc буде виглядати дещо інакше від описаного в першому розділі "Компіляція програм мовою C / C + +".
Компілювати можна всі файли одночасно однією командою, перераховуючи складові файли через пробіл після ключа-c:
gcc-c main.c f1.c f2.c
Або кожен файл окремо:
gcc-c f1.c
gcc-c f2.c
gcc-c main.c
У результаті роботи компілятора ми отримаємо три окремих об'єктних файлу:
main.o
f1.o
f2.o
Щоб їх зібрати в один файл за допомогою gcc треба використовувати ключ-o, при цьому лінкер збере всі файли в один:
gcc main.o f1.o f2.o-o rezult
У результаті виклику отриманої програми rezult командою:
. / Rezult
На екрані з'явиться результат роботи:
olya: ~ #. / rezult
f1 () = 2
f2 () = 10
olya: ~ #
Тепер, якщо ми змінимо якусь із процедур, наприклад f1 ():
int f1 ()
{
return 25;
}
Те компілювати наново всі файли не доведеться, а треба буде лише скомпілювати змінений файл і зібрати результуючий файл з шматків:
olya: ~ # gcc-c f1.c
olya: ~ # gcc main.o f1.o f2.o-o rezult2
olya: ~ # ./rezult2
f1 () = 25
f2 () = 10
olya: ~ #
Таким чином можна створювати великі проекти, які більше не будуть віднімати багато часу на компіляцію і пошук помилок. Однак потрібно пам'ятати, що не варто також черезчур розбивати програму, інакше в нас вийде кілька десятків файлів, в яких рано чи пізно можна заплутатися. Можна знайти "золоту середину", наприклад в окремі файли поміщати ті функції чи класи, з якими нам доводиться найбільше працювати при налагодженні. Після того, як функція буде остаточно налагоджена, її цілком можна перенести в більш великий файл.

3 Створення бібліотек об'єктних файлів
3.1 Бібліотеки об'єктних файлів
У минулому розділі курсової роботи ми створювали об'єктні файли. Природно, якщо кожна функція буде міститися в окремому файлі, то таких файлів може виявитися десятки або навіть сотні. Управляти такою кількістю файлів дуже складно. Для цього був придуманий механізм створення бібліотек об'єктних файлів.
Бібліотека об'єктних файлів - це файл, що містить кілька об'єктних файлів, які будуть використовуватися разом у стадії компонування програми. Нормальна бібліотека містить символьний індекс, який складається з назв функцій і змінних і т.д., які містяться в бібліотеці. Це дозволяє прискорити процес компонування програми, тому що пошук функцій і змінних в об'єктних файлах бібліотеки відбувається набагато швидше, ніж пошук в наборі зазначених об'єктних файлів. Тому використання бібліотеки дозволяє компактно зберігати всі необхідні об'єктні файли в одному місці, і при цьому значно підвищити швидкість компіляції.
Об'єктні бібліотеки за способом використання поділяються на два види:
· Статичні бібліотеки
· Динамічні бібліотеки
Статична бібліотека - це колекція об'єктних файлів, які приєднуються до програми під час компонування програми. Таким чином статичні бібліотеки використовуються тільки при створенні програми. Потім у роботі самої програми вони не приймають участь, на відміну від динамічних бібліотек.
Динамічна бібліотека - це створена спеціальним чином бібліотека, яка приєднується до результуючої програмі в два етапи. Перший етап, це природно етап компіляції. На цьому етапі лінковщік вбудовує у програму опису необхідних функцій і змінних, які присутні в бібліотеці. Самі об'єктні файли з бібліотеки не приєднуються до програми. Приєднання цих об'єктних файлів (кодів функцій) здійснює системний динамічний завантажувач під час запуску програми. Завантажувач перевіряє всі бібліотеки прілінкованние з програмою на наявність необхідних об'єктних файлів, потім завантажує їх в пам'ять і приєднує їх в копії запущеної програми, що знаходиться в пам'яті.
Складний процес завантаження динамічних бібліотек уповільнює запуск програми, але у нього є существунний, навіть можна сказати неоціненний плюс - якщо інша програма, що запускається лінковані з цією ж завантаженої динамічної бібліотекою, то вона використовує тугіше копію бібліотеки. Це означає, що потрібно набагато менше пам'яті для запуску кількох програм, самі завантажувальні файли менше за розміром, що заощаджує місце на дисках.
Однак якщо Ви вносите динамічну бібліотеку і спробуєте її використовувати при запуску програми, то якщо завантажувач виявить вже завантажену стару бібліотеку він буде наполегливо використовувати її функції. При цьому Ви так і не зможете завантажити нову версію бібліотеки. Але є шляхи вирішення цієї проблеми, і їх ми розглянемо пізніше.

3.2 Створення статичної бібліотеки
Для створення статичних бібліотек існує спеціальна проста програма звана ar (скор. від archiver - архіватор). Вона використовується для створення, модифікації та перегляду об'єктних файлів в статичних бібліотеках, які насправді представляють із себе прості архіви.
Створимо з файлів f1.c і f2.c окрему бібліотеку.
/ / Файл f1.c
int f1 ()
{
return 2;
}
/ / Файл f2.c
int f2 ()
{
return 10;
}
Для початку компілюємо ці файли:
olya: ~ # gcc-c f1.c f2.c
У результаті отримаємо, як зазвичай, два файли - f1.o і f2.o. Для того, щоб створити бібліотеку з об'єктів файлів треба викликати програму ar з наступними параметрами:
ar rc libімя_бібліотекі. a [спісок_ *. o_файлов]
Припустимо наша бібліотека буде називатися fs, тоді команда запишеться у вигляді:
olya: ~ # ar rc libfs.a f1.o f2.o
У результаті отримаємо файл libfs.a, в якому будуть лежати копії об'єктами файлу f1.o і f2.o. Якщо файл бібліотеки вже існує, то архіватор буде аналізувати вміст архіву, він додасть нові об'єктні файли і замінить старі оновленими версіями. Опція c змушує створювати (від create) бібліотеку, якщо її немає, а опція r (від replace) замінює старі об'єктні файли новими версіями.
Поки у нас є лише архівний файл libfs.a. Щоб з нього зробити повноцінну бібліотеку об'єктних файлів треба додати до цього архіву індекс символів, тобто список вкладених в бібліотеку функцій і змінних, щоб лінкування відбувалася швидше. Далай це командою:
ranlib libімя_бібліотекі. a
Програма ranlib додасть індекс до архіву і вийде повноцінна статична бібліотека об'єктних файлів. Варто відзначити, що на деяких системах програма ar автоматично створює індекс, і використання ranlib не має ніякого ефекту. Але тут треба бути обережним при атоматіческі компіляції бібліотеки за допомогою файлів makefile, якщо не використовувати утиліту ranlib, то можливо на якихось системах бібліотеки будуть створюватися не вірно і загубиться незалежність від платформи. Так що візьмемо за правило той факт, що утиліту ranlib треба запускати в будь-якому випадку, навіть якщо він неї немає ніякого ефекту.
Для компіляції нашого основного файлу main.c треба повідомити компілятору, що треба використовувати бібліотеки. Щоб компілятор знав де шукати бібліотеки йому треба повідомити каталог, в якому вони містяться і список цих біліотек. Каталог з бібліотеками вказується ключем-L, у нашому випадку бібліотека знаходиться в поточному каталозі, значить шлях до неї буде у вигляді точки (-L.). Використовувані бібліотеки перераховуються через ключ-l, після якого вказується назва бібліотеки без префікса lib і закінчення. A. У нашому випадку цей ключ буде виглядати, як-lfs. Тепер все однією командою:
olya: ~ # gcc-c main.c
olya: ~ # gcc main.o-L. -Lfs-o rezult
Або можна трохи коротше:
olya: ~ # gcc main.c-L. -Lfs-o rezult
Зауважте, що компілятору потрібні бібліотеки на етапі створення кінцевого файлу, тобто компонування. У першому випадку процес компіляції відбувається першою командою, а складання файлу другою командою. Якщо ж ми спробуємо підсунути бібліотеку на етапі компіляції, то отримаємо ввічлива відповідь:
olya: ~ # gcc-c main.c-L. -Lfs
gcc:-lfs: linker input file unused since linking not done
Що означає, що файли бібліотек не потрібні, до процесу компонування. Ця команда створить лише файл main.o, який у результаті потім доведеться збирати окремо.
3. 3 Створення динамічної бібліотеки
Як ми вже говорилося в курсовій роботі, динамічні бібліотеки трохи краще статичних, але їх використання більш складне. І не через те, що процес завантаження програми сповільнюється. Проблеми починаються вже на етапі компіляції.
Для початку варто сказати, що об'єктний файл створюваний нашим перевіреним способом зовсім не підходить для динамічних бібліотек. Пов'язано це з тим, що всі об'єктні файли створювані звичайним чином не мають уявлення про те в які адреси пам'яті буде завантажена використовує їх програма. Кілька різних програм можуть використовувати одну бібліотеку, і кожна з них розташовується в різному адресному просторі. Тому потрібно, щоб переходи у функціях бібліотеки (операції goto на асемблері) використовували не абсолютну адресацію, а відносну. Тобто генерований компілятором код повинен бути незалежним від адрес, така технологія отримала назву PIC - Position Independent Code. У компіляторі gcc дана можливість вмикається ключем-fPIC.
Тепер компілювання наших файлів буде мати вигляд:
olya: ~ # gcc-fPIC-c f1.c
olya: ~ # gcc-fPIC-c f2.c
Динамічна бібліотека це вже не архівний файл, а справжня завантажувана програма, тому створенням динамічних бібліотек займається сам компілятор gcc. Для того, щоб створити динамічну бібліотеку треба використовувати ключ-shared:
olya: ~ # gcc-shared-o libfsdyn.so f1.o f2.o
У результаті отримаємо динамічну бібліотеку libfsdyn.so, яка за моєю задумом буде динамічної версією бібліотеки libfs.a, що видно з назви:) Тепер, щоб компілювати результуючий файл з використанням динамічної бібліотеки нам треба зібрати файл командою:
olya: ~ # gcc-с main.с
olya: ~ # gcc main.o-L. -Lfsdyn-o rezultdyn
Якщо тепер Ви порівняйте файли, отримані при використанні статичної та динамічної бібліотеки, то побачите, що їх розміри відрізняються. У даному випадку файл створений з динамічною бібліотекою займає трохи більше місця, але це лише від того, що програма використовувана нами зовсім примітивна і левову частку там займає спеціальний код для використання динамічних можливостей. У реальних умовах, коли використовуються дуже великі функції розмір програми з використанням динамічної бібліотеки значно менше.
На цьому фокуси не закінчуються, якщо Ви зараз спробуєте запустити файл rezultdyn, то отримаєте помилку:
olya: ~ #. / rezultdyn
. / Rezultdyn: error in loading shared libraries: libfsdyn.so: cannot open
shared object file: No such file or directory
olya: ~ #
Це повідомлення видає динамічний лінковщік. Він просто не може знайти файл нашої динамічної бібліотеки. Справа в тому, що завантажувач шукає файли динамічних бібліотек у відомих йому директоріях, а наша директорія йому не відома. Але це ми трохи відкладемо, бо це досить складне питання.
А зараз варто поговорити ще про один момент використання бібліотек. Ми спеціально динамічну бібліотеку з назвою fsdyn, щоб вона відрізнялася від назви статичної бібліотеки fs. Справа в тому, що якщо у Вас дві бібліотеки статична і динамічна з однаковими назвами, тобто libfs.a і libfs.so, то компілятор завжди буде використовувати динамічну бібліотеку.
Пов'язано це з тим, що в ключі-l задається частина імені бібліотеки, а префікс lib і закінчення. A або. So приставляє сам компілятор. Так ось алгоритм роботи компілятора такий, що якщо є динамічна бібліотека, то вона використовується за умовчанням. Статична ж бібліотека використовується коли компілятор не може знайти файл. So цієї бібліотеки. У всій наявною у мене документації пишеться, що якщо використовувати ключ-static, то можна насильно змусити компілятор використовувати статичну бібліотеку. Дуже добре, спробуємо ...
olya: ~ # gcc-staticmain.o-L. -Lfs-o rez1
Результуючий файл rez1 виходить розміром в 900 Кб. Після застосування програми stri p розмір її зменшується до 200 Кб, але це ж не порівняти з тим, що наша перша статична компіляція давала програму розміром 10 Кб. А пов'язано це з тим, що будь-яка програма написана на C / C + + в Linux використовує стандартну бібліотеку "C" library, яка містить у собі визначення таких функцій, як printf (), write () і всіх інших. Ця бібліотека лінків до файлу як динамічна, щоб всі програми написані на C + + могли використовувати один раз завантажені функції. Ну, а при вказуванні ключа-static компілятор робить лінковки libc статичної, тому розмір коду збільшується на всі 200 Кб.

3.4 Використання динамічних бібліотек
Минулого разу ми з Вами виявили, що запуск програм, скомпільованих разом з динамічними бібліотеками, викликає помилку:
olya: ~ #. / rezultdyn
. / Rezultdyn: error in loading shared libraries: libfsdyn.so: cannot open
shared object file: No such file or directoryolya: / #
Це повідомлення видає завантажувач динамічних бібліотек (динамічний лінковщік - dynamic linker), який в нашому випадку не може виявити бібліотеку libfsdyn.so. Для налаштування динамічного лінковщіка існує ряд програм.
Перша програма називається ldd. Вона видає на екран список динамічних бібліотек використовуються в програмі і їх місце розташування. Як параметр їй повідомляється назва обстежуваної програми. Давайте спробуємо використовувати її для нашої програми rezultdyn:
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 odivdelitel 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с.
Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Курсова
55.7кб. | скачати


Схожі роботи:
Розробка статичних і динамічних бібліотек на мові програмування СC в операційних
Системне програмування в операційних системах
Розробка алгоритмів та програмування різних обчислювальних процесів на мові Delphi
Збереження даних в операційних системах
Подання знань в агентних системах на прикладі системи Internet Knowledge Manager та динамічних
Методи обробки динамічних сцен при впливі нестаціонарних завад у радіотехнічних системах супроводження
Аналіз криптостійкості методів захисту інформації в операційних системах Microsoft Window 9x
Аналіз криптостійкості методів захисту інформації в операційних системах Microsoft Windows 9x
Розробка динамічних моделей для транспортно виробничої системи
© Усі права захищені
написати до нас