Когда и зачем нам использовать библиотеки?

Представьте, что вы пишете статью об эволюции и истории черепах на Мадагаскаре. Вы просто хотите сразу погрузиться в сочинение о черепахах и не хотите, чтобы вас беспокоили перефразирование всей теории эволюции Дарвина. Естественно, вы просто вызываете его теорию по имени: «Теория эволюции Дарвина». Кроме того, вы цитируете основополагающую книгу Дарвина «Происхождение видов», чтобы те, кто не знает, что такое «теория эволюции», могут перейти в библиотеку и посмотрите, что на самом деле означают эти три слова в сочетании.

Библиотеки 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

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

gcc -shared -o libalphabet.so *.o

Наконец, если вы хотите проверить и увидеть, какие именно функции содержатся в вашей недавно созданной библиотеке, вы можете использовать команду nm с флагом -D, который ссылается на символы в разделе инициализированных данных.

nm -D libalphabet.so

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

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

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

Статическая компоновка имеет несколько недостатков по сравнению с динамической компоновкой.

  • Размер: каждая функция в вашей программе будет иметь объектный код, связанный напрямую. Это эквивалентно копированию и вставке «Происхождение видов» каждый раз, когда вы хотите сказать «теория эволюции». Что, как вы понимаете, сделало бы ваше эссе о черепахах гораздо более громоздким и неэффективным, чем должно быть.
  • Обновления: если библиотека, которую вы статически связали, обновлена ​​(для исправления ошибки или чего-то еще), вам необходимо перекомпилировать всю вашу программу.

Рассмотрим функцию print_alphabet(). Он находится в файле с именем print_alphabet.c и выглядит примерно так:

#include <stdio.h>
void print_alphabet(void)
{
     printf("abcdefghijklmnopqrstuvwxyz");
}
  • #include <stdio.h> включает стандартную библиотеку ввода-вывода C, в которой есть printf() функция.
  • printf() - это стандартная библиотечная функция, которая просто печатает строку.

Наша print_alphabet() функция не делает ничего кричащего; он делает одну вещь и делает это хорошо: печатает алфавит.

Мы можем преобразовать эту программу в объектный код, используя следующую команду:

gcc -c print_alphabet.c

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

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

Static libraries:
╔════════════════════════════╦══════════════════════════════╗
║            Pros            ║             Cons             ║
╠════════════════════════════╬══════════════════════════════╣
║ 1. No runtime dependencies ║ 1. Uses lots of memory       ║
║                            ║ 2. Needs to be recompiled if ║
║                            ║    updated                   ║
╚════════════════════════════╩══════════════════════════════╝
                            vs.
Dynamic libraries:
╔════════════════════════════╦════════════════════════════╗
║            Pros            ║            Cons            ║
╠════════════════════════════╬════════════════════════════╣
║ 1. Takes up less memory    ║ 1. Library must be present ║
║                            ║    in order for program    ║
║                            ║    to run                  ║
║ 2. Don't need to recompile ║ 2. Less portable           ║
║    main program following  ║                            ║
║    an update               ║                            ║
╚════════════════════════════╩════════════════════════════╝

Спасибо за прочтение.