Разделяемая библиотека
Разделяемая библиотека (также динамическая библиотека, разделяемый объект, от англ. shared library) — это файл, содержащий исполняемый код и данные, предназначенный для использования одновременно несколькими независимыми программами (процессами) в операционной системе. В отличие от статической библиотеки, код которой копируется в каждый исполняемый файл на этапе компиляции и компоновки, код разделяемой библиотеки загружается в память только при запуске программы или по требованию во время её выполнения. Это позволяет экономить дисковое пространство, оперативную память и упрощает обновление программного обеспечения.
История
Концепция разделяемых библиотек возникла как развитие идей модульного программирования и многозадачности. В ранних операционных системах, таких как MS-DOS, все библиотеки были статическими — каждая программа содержала полный набор необходимых ей функций. Это приводило к значительному дублированию кода на диске и в памяти.
Первые шаги к динамическому связыванию были сделаны в операционной системе Multics (1960-е годы), где код мог разделяться между процессами. В коммерческих системах Unix разделяемые библиотеки появились в конце 1980-х годов (например, в SunOS 4.0). В мире Windows аналогом стали динамически подключаемые библиотеки (DLL, Dynamic Link Library), введённые в Windows 1.0 (1985 год).
В России и странах бывшего СССР развитие системного программирования шло параллельно. В операционных системах для советских ЭВМ (например, ОС ЕС ЭВМ, ОС ДВК) также применялись механизмы, напоминающие разделяемые библиотеки, хотя они были менее гибкими и стандартизированными, чем в западных аналогах. Широкое распространение разделяемые библиотеки получили в Linux и других Unix-подобных системах с появлением стандарта ELF (Executable and Linkable Format) в 1990-х годах.
Принцип работы
Разделяемая библиотека представляет собой отдельный файл, который не является исполняемым сам по себе (не имеет точки входа main). При запуске программы, которая использует такую библиотеку, операционная система выполняет следующие действия:
- Загрузка: Загрузчик ОС (динамический компоновщик, например,
ld.soв Linux илиntdll.dllв Windows) находит файл библиотеки по указанному пути (обычно в системных каталогах или в каталоге программы). - Связывание: Загрузчик подставляет адреса функций и глобальных переменных из библиотеки в таблицы импорта программы.
- Разделение памяти: Если одна и та же библиотека уже загружена другим процессом, ОС (при использовании механизма copy-on-write) может отобразить её код в адресное пространство нового процесса без повторного чтения с диска. Данные библиотеки (глобальные переменные) обычно копируются для каждого процесса, чтобы избежать конфликтов.
Связывание во время выполнения
Существует два основных режима связывания:
- Динамическое связывание при загрузке (load-time dynamic linking): Библиотека загружается автоматически при запуске программы. Программа заранее знает, какие функции ей нужны. Это самый распространённый способ.
- Динамическое связывание во время выполнения (run-time dynamic linking): Программа сама явно загружает библиотеку (например, с помощью функций
dlopenв POSIX-системах илиLoadLibraryв Windows) и получает адреса нужных функций во время своей работы. Это используется для реализации плагинов, драйверов и гибких архитектур, где набор модулей неизвестен заранее.
Классификация и форматы
Разделяемые библиотеки существуют в различных форматах, которые зависят от операционной системы и архитектуры процессора.
Основные форматы
| Формат | Операционная система | Расширение файла |
|---|---|---|
| ELF (Executable and Linkable Format) | Linux, Unix, FreeBSD, Android | .so (shared object) |
| PE (Portable Executable) | Windows | .dll (Dynamic Link Library) |
| Mach-O | macOS, iOS | .dylib (dynamic library) или .framework |
| COFF (Common Object File Format) | Устаревшие Unix-системы, MS-DOS | .dll |
Типы по способу использования
- Системные библиотеки: Входят в состав ОС (например,
libc.soв Linux — библиотека языка C,kernel32.dllв Windows). Они предоставляют базовый API для работы с файлами, памятью, процессами. - Библиотеки приложений: Поставляются вместе с конкретной программой (например,
libQt5Core.soдля приложений на Qt). - Плагины и модули: Загружаются динамически во время выполнения для расширения функциональности основной программы (например, фильтры в графическом редакторе, модули веб-сервера Apache).
Преимущества и недостатки
Преимущества
- Экономия ресурсов: Код библиотеки хранится на диске в одном экземпляре и загружается в память только один раз для всех использующих её программ. Это особенно важно для больших системных библиотек (например, графических, сетевых).
- Упрощение обновлений: Для исправления ошибки или добавления новой функции достаточно заменить один файл библиотеки, не перекомпилируя все программы, которые её используют. Это является основой системы пакетных менеджеров в Linux.
- Модульность: Разработчики могут создавать крупные проекты, разбивая их на независимые, слабо связанные модули (библиотеки). Это упрощает разработку, тестирование и поддержку кода.
- Гибкость: Возможность загрузки библиотек во время выполнения позволяет создавать архитектуры с подключаемыми плагинами, что широко используется в играх, веб-браузерах и САПР.
Недостатки
- «Ад DLL» (DLL Hell): В Windows исторически возникала проблема, когда разные программы требовали разные версии одной и той же DLL. Установка новой программы могла перезаписать системную библиотеку, что приводило к поломке других приложений. В современных ОС эта проблема решается с помощью механизмов изоляции (side-by-side assemblies, манифесты) и контейнеризации.
- Зависимость от версий: Программа может перестать работать, если в системе отсутствует нужная версия разделяемой библиотеки. Это требует тщательного управления зависимостями (например, с помощью менеджеров пакетов
apt,yum). - Снижение производительности: Динамическое связывание требует дополнительного времени на загрузку библиотеки и разрешение символов (поиск адресов функций). В современных системах этот накладной расход минимизирован за счёт кэширования и предзагрузки.
- Уязвимости безопасности: Ошибка в одной разделяемой библиотеке (например, в
libssl) может затронуть все программы, которые её используют. Это делает библиотеки критической точкой атаки.
Применение
Разделяемые библиотеки являются фундаментом современных операционных систем и программного обеспечения. Они используются повсеместно:
- Операционные системы: Ядро Linux, Windows, macOS активно используют разделяемые библиотеки для реализации драйверов устройств, сетевых протоколов, файловых систем и графического интерфейса.
- Прикладное ПО: Веб-браузеры (Chrome, Firefox), офисные пакеты (LibreOffice, Microsoft Office), графические редакторы (GIMP, Krita) — все они состоят из десятков и сотен разделяемых библиотек.
- Языки программирования: Интерпретаторы и виртуальные машины (Python, Java, .NET) загружают разделяемые библиотеки для реализации встроенных функций и модулей расширения (например,
.pydв Python,.soв Java JNI). - Игры: Игровые движки (Unreal Engine, Unity) используют разделяемые библиотеки для загрузки игровых уровней, моделей, звуков и скриптов во время игры.
Разделяемые библиотеки в России
В российской IT-индустрии разделяемые библиотеки являются стандартным инструментом. Разработка на языках C, C++, Rust, Go и других активно использует динамическое связывание. В рамках импортозамещения и развития отечественных операционных систем (например, Astra Linux, ALT Linux, РЕД ОС) активно используются стандартные форматы ELF и механизмы разделяемых библиотек, совместимые с Linux. Разработка собственных библиотек (например, для криптографии, работы с базами данных, графики) ведётся в компаниях «Лаборатория Касперского», «1С», «Яндекс» и многих других.
Интересные факты
- Самая известная разделяемая библиотека в мире —
libc.so(илиmsvcrt.dll). Она содержит базовые функции языка C (printf, malloc, fopen) и используется практически каждой программой. - В Linux существует утилита
ldd, которая показывает, какие разделяемые библиотеки требуются для запуска конкретного исполняемого файла. - Механизм разделяемых библиотек лежит в основе технологии контейнеризации (Docker, Podman). Контейнер содержит только необходимые библиотеки, что делает его лёгким и изолированным.
- В операционной системе Windows библиотеки DLL часто используются для реализации COM-объектов (Component Object Model), что позволяет создавать компоненты, которые могут быть использованы из разных языков программирования.
Источники
- Таненбаум Э., Бос Х. «Современные операционные системы». 4-е издание. — СПб.: Питер, 2015.
- Левин Дж. «Linkers and Loaders». — Morgan Kaufmann, 1999.
- Документация по формату ELF (Executable and Linkable Format) — стандарт TIS (Tool Interface Standard).
- Документация Microsoft по динамически подключаемым библиотекам (DLL) — MSDN.
- Статья «Shared library» в англоязычной Википедии (версия от 2023 года).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →