Статични срещу динамични библиотеки в С

Кога и защо бихме използвали библиотеки?

Представете си, че пишете статия за еволюцията и историята на костенурките в Мадагаскар. Просто искате да се потопите право в писането за костенурки и не искате да се притеснявате да преразглеждате цялата теория на еволюцията на Дарвин. Естествено, вие просто се позовавате на неговата теория по име: „Теорията на еволюцията на Дарвин“. Освен това цитирате семенната книга на Дарвин, „За произхода на видовете“, така че тези, които не знаят какво е „теорията на еволюцията“, могат да отидете в библиотеката и вижте какво точно означават тези три думи, когато са комбинирани.

C библиотеките са изградени повече или по-малко на една и съща предпоставка: човек може да спести много време и усилия, като използва повторно работата, която някой (включително и миналото ви) вече е направил. Ние също се възползваме от факта, че Дарвин вероятно е артикулирал теорията си по-добре, отколкото можем, и по подобен начин колективното съзнание на разработчиците, които са работили върху нещо като стандартната библиотека C, най-вероятно са написали по-здрава функция за отпечатване на низ, отколкото можехме да дадем време ограничения (поне това е вярно в моя случай).

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

Как да създадете статична библиотека в Linux?

За да създадем статични библиотеки, използваме командата ar, която означава програмата „архиватор“. Тази програма може да създава, изброява и променя статични библиотеки или „архивни файлове“ от нашия команден ред.

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

ar -r -c libalphabet.a print_alphabet.o

Тази команда създава статична библиотека, наречена libalphabet.a и поставя копие на файла print_alphabet.o в нея.

  • Флагът -r казва на архиватора да замени всички по-стари обектни файлове с по-новите обектни файлове.
  • Флагът -u указва на архиватора да създаде файла libalphabet.a, ако той не съществува.

Но това не е всичко. Ние можем и трябва да индексираме нашата библиотека, така че компилаторът да намери нашите свързани програми по-бързо и по-ефективно. Командата за създаване на индекс на нашата библиотека (или актуализиране на съществуващ индекс) е ranlib, която приема нашата библиотека като аргумент:

ranlib libalphabet.a

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

За да видите съдържанието на нашата библиотека, можем да използваме ar -t комбо. Но ако искаме още повече информация, тогава можем да използваме командата nm. Тази команда изброява стойността, типа и името на всеки символ.

Как да създадете динамична библиотека в Linux?

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

gcc -c -fPIC * .c

След това трябва да конвертираме този код на обектния код в споделена библиотека. Вместо да използваме инструмента за архивиране, както направихме при генерирането на статична библиотека, използваме флаг-споделеното в друг цикъл с gcc. Уверете се, че сте включили флага -o, за да дадете на библиотеката си персонализирано име. Библиотеката се нуждае от разширение .so за споделен обект и по споразумение префиксът lib, за да посочи, че е библиотека. За да включим всички наши обектни кодове, използваме wildcard *, последвано от разширението .o (обект файл).

gcc -shared -o libalphabet.so * .o

И накрая, ако искате да проверите и да видите коя точно функция се съдържа в новосъздадената ви библиотека, можете да използвате командата nm с флаг -D, който препраща символите в секцията с инициализирани данни.

nm -D libalphabet.so

Кои са основните разлики между статичните и динамичните библиотеки?

Статичните библиотеки се различават от динамичните (понякога наричани: споделени) библиотеки в това, че статичният библиотечен код е свързан директно във вашия окончателен изпълним файл.

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

Статичното свързване има няколко недостатъка в сравнение с динамичното свързване.

  • Размер: всяка функция във вашата програма ще има директно свързан код на обекта. Това е еквивалент на копиране и поставяне на „От произхода на видовете“ всеки път, когато искате да кажете „теория на еволюцията“. Което, както можете да си представите, би направило есето ви за костенурките много по-обемно и неефективно, отколкото трябва да бъде.
  • Актуализации: ако библиотеката, към която сте свързани статиката, се актуализира (за отстраняване на грешка или нещо подобно), тогава трябва да прекомпилирате цялата си програма.

Помислете за функцията print_alphabet (). Той се намира във файл, наречен print_alphabet.c и изглежда така:

#include 
void print_alphabet (void)
{
     ФОРМАТ ( "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
  • #include включва библиотеката на C / I стандарт, която има функцията printf ().
  • printf () е стандартна библиотечна функция, която просто отпечатва низ.

Нашата print_alphabet () функция не прави нищо светкавично; прави едно нещо и го прави добре: отпечатване на азбуката.

Можем да преобразуваме тази програма в обект код, използвайки следната команда:

gcc -c print_alphabet.c

Нашият файл вече е print_alphabet.o и съдържа обект код вместо изходен код. Този обективен код е директно поставен във всяка програма, която използва статичната библиотека, съдържаща функцията print_alphabet (): статично свързване с две думи.

Какви са плюсовете и минусите на статичните и динамичните библиотеки?

Статични библиотеки:
╔════════════════════════════╦════════════════════ ══════════╗
║ плюсове ║ минуси ║
╠════════════════════════════╬════════════════════ ══════════╣
║ 1. Без зависимости от време на изпълнение ║ 1. Използва много памет ║
Ne ║ 2. Необходимо е да се прекомпилира, ако ║
║ ║ актуализиран ║
╚════════════════════════════╩════════════════════ ══════════╝
                            срещу.
Динамични библиотеки:
╔════════════════════════════╦════════════════════ ════════╗
║ плюсове ║ минуси ║
╠════════════════════════════╬════════════════════ ════════╣
║ 1. Заема по-малко памет ║ 1. Библиотеката трябва да присъства ║
║ ║ за програма for
║ ║ да тичам ║
║ 2. Не е необходимо да компилирате ║ 2. По-малко преносими ║
║ основна програма след ║ ║
║ актуализация ║ ║
╚════════════════════════════╩════════════════════ ════════╝

Благодаря за четенето.