В тази публикация в блога ще обсъдя статичните и динамичните библиотеки и ще изследвам следното: защо трябва да използвате библиотека, как работят, как се създават тези библиотеки на машини с Linux, как да ги използвате с вашия код, сравнете и противопоставете двете като както и проучете недостатъците на двете библиотеки като цяло.

Отказ от отговорност: Преди да прочетете, моля, имайте предвид, че това е публикация в блог, създадена в по-голямата си част от мое собствено онлайн проучване и личен опит. Аз съм студент и следователно в никакъв случай не съм експерт по тази тема. Имайки предвид това, надявам се, че намирате съдържанието за приятно полезен ресурс и предоставя алтернативна мярка за по-лесно разбиране от гледна точка на студентите.

Защо трябва да използвате библиотека?

Библиотеките по същество са просто колекции от компилиран код, който съществува във вашата машина в определени папки (ще разширим това по-късно). Тези библиотеки се добавят към вашия код по време на процеса на компилиране на етапа на свързване. Библиотеките са прекрасни инструменти, тъй като ви позволяват да използвате повторно код, който е бил написан преди това от друг програмист или от вас самите. Можете да използвате функции в тези библиотеки, без да се притеснявате за компилирането или дори как работи вътрешният код. Това от своя страна ще ви позволи да се съсредоточите върху текущия проблем, вместо да се тревожите за подробности за изпълнението на споменатите функции. Да кажем например, че пишете програма, в която трябва да се изчисли дължината на число. Бихте могли да напишете функция, която ви дава този отговор, но ако има библиотека, която вече съдържа такава функция, всичко, което трябва да направите, е да я импортирате и да я използвате, вместо да започнете от нулата; лесно, бързо и просто.

Как работят библиотеките?

Както споменах по-рано, библиотеката се добавя към вашия код по време на процеса на компилиране на етапа на свързване. Това е точно, но именно тук начинът, по който се добавя кодът, до голяма степен разграничава статичните от динамичните библиотеки.

За статични библиотеки етапът на свързване добавя действителния двоичен файл на библиотеката към двоичния файл на кода, който възнамерява да използва библиотеката към изпълним файл. Това е основният недостатък на статичните библиотеки; колкото повече библиотеки използвате, толкова по-голям ще бъде размерът на изпълнимия файл. Друг недостатък е, че ако библиотеката се актуализира, вашият изпълним файл няма да е наясно с промените и ще трябва да прекомпилирате кода си, за да можете да приложите нови актуализации. Динамичните библиотеки обаче имат различен подход; линкерът ще добави само адреса, където се намира библиотеката, коригирайки както проблемите с размера, така и с актуализацията. Това е много по-удобен подход от статичната библиотека, изискваща добавяне на двоичен код към кода на приложението към изпълним файл.

Като се има предвид това, ако динамичните библиотеки решават толкова много проблеми, защо изобщо съществуват статичните библиотеки? Помислете как работи една динамична библиотека; осъзнайте, че получаването на актуализация на тази библиотека означава загуба на предишната версия, която е била предварително инсталирана във вашия компютър. Това може да причини някои сериозни проблеми, ако има грешки или вашият код не е съвместим с по-новата версия. Това беше известно като DLL-Hell (Dynamic Link Library Hell), но беше разрешено в по-нови версии на операционната система, като се даде възможност на програмиста да версиира библиотеки. Поради тази причина динамичните библиотеки се считат за по-добрият подход през повечето време.

Създаване на статична библиотека

След като сте готови да компилирате вашата програма, направете следното:

Компилирайте всичките си C файлове в обектни файлове

Можете да видите, че съм използвал следните опции за компилиране:

  • -c : Компилирайте или асемблирайте изходните файлове, но не свързвайте.
  • -Стена : Включете всички предупреждения.
  • -Wextra : Активира допълнителни предупредителни флагове, които не са активирани от -Wall.
  • -Грешка: Превърнете всички предупреждения в грешки.
  • -педантичен: Издайте всички предупреждения, изисквани от строгите ISO C и ISO C++.

Вижте gcc man страницата за повече подробности.

Сега използвайте програмата arза да създадете архив.

  • r: За да вмъкнете файловете в архива.
  • c: За да създадете архива.
  • s: За да запишете индекса на обектните файлове в архива или да актуализирате съществуващ.

По избор:

Използвайте ranlib, за да генерирате индекс за архивиране. Забележка: Забелязвате как ar s прави същото като ranlib? Това е така, защото изпълнението на ar s върху архив е еквивалентно на изпълнението на ranlib.

Създаване на динамична библиотека

След като сте готови да компилирате своя код, направете следното:

Компилирайте всичките си C файлове в обектни файлове

Можете да видите, че използвах следните опции за компилиране:

  • -fPIC: Директива на компилатора за извеждане на код, независим от позицията. Това е необходимо, за да се създават споделени библиотеки. Вижте също -fpic.
  • -c : Компилирайте или асемблирайте изходните файлове, но не свързвайте.
  • -Стена : Включете всички предупреждения.
  • -Wextra : Активира допълнителни предупредителни флагове, които не са активирани от -Wall.
  • -Werror: Превърнете всички предупреждения в грешки.
  • -педантичен: Издайте всички предупреждения, изисквани от строгите ISO C и ISO C++.

Вижте gcc man страницата за повече подробности.

След това използвайте флага „-shared“, за да създадете споделен обект, който след това може да бъде свързан с други обекти, за да образува изпълним файл.

Помните ли как споменах, че библиотеките съществуват в определени директории? След като създаде динамичната библиотека, компилаторът трябва да знае къде да намери споменатата библиотека. Имате множество опции; първото от които е просто да копирате или преместите динамичната библиотека, която току-що сте създали, в/usr/libили /usr/local/lib папка. Като алтернатива, ако нямате достъп за писане в тази папка, можете да настроите променливата на средата LD_LIBRARY_PATHкъм пътя, в който съществува вашата библиотека. Предупреждение: Внимавайте да не изтриете текущата стойност на променливата LD_LIBRARY_PATH.

експортиране на LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

За да използвате тези библиотеки с вашия код, просто включете заглавката, която съдържа прототипите за функциите в библиотеката и след това компилирайте както обикновено.

Да обобщим:

Статични библиотеки

  • Копирайте директно във вашия изпълним файл.
  • Изпълнимият файл не се актуализира автоматично, когато има промяна в библиотеката.
  • По-големи изпълними файлове.
  • Използва командитеarи runlib.
  • Имат префикс lib и разширение .a.

Динамични библиотеки

  • В изпълнимия файл се посочва само адресът на библиотеката.
  • Изпълнимият файл се актуализира, когато се срещне нова версия на библиотеката.
  • Ако не се използва управление на версиите, то ще презапише предишните версии на библиотеката, което вероятно ще повреди вашия изпълним файл.
  • По-малки изпълними файлове.
  • Използва gcc с флаговете-fPICи -shared.
  • Имат префикс lib и разширение .so.