sysbin.com
Библиотека — это набор скомпонованных особым образом объектных файлов. Библиотеки подключаются к основной программе во время линковки. По способу компоновки биб- лиотеки подразделяют на архивы (статические библиотеки, static libraries) и совместно используемые (динамические библиотеки, shared libraries). В Linux, кроме того, есть меха- низмы динамической подгрузки библиотек. Суть динамической подгрузки состоит в том, что запущенная программа может по собственному усмотрению подключить к себе какую- либо библиотеку. Благодаря этой возможности создаются программы с подключаемыми плагинами, такиекак XMMS.
Статическая библиотека — это просто архив объектных файлов, который подключается к программе во время линковки. Эффект такой же, как при компиляции файлов отдельно.
В отличие от статических библиотек, код совместно используемых (динамических) биб- лиотек не включается в бинарник. Вместо этого в бинарник включается только ссылка на библиотеку.
Рассмотрим преимущества и недостатки статических и совместно используемых библиотек. Статические библиотеки делают программу более автономной: программа, скомпонован- ная со статической библиотекойможет запускаться на любом компьютере, не требуя наличия этой библиотеки (онауже «внутри»бинарника). Программа, скомпонованная с динамической библиотекой, требует наличия этой библиотеки на том компьютере, где она запускается, поскольку в бинарнике некод, а ссылка накод библиотеки. Не смотря на такую зависимость, динамические библиотеки обладают двумя существенными преиму- ществами. Во-первых, бинарник, скомпонованный с совместно используемой библиотекой меньше размером, чем такой же бинарник, с подключенной к нему статической библиотекой (статически скомпонованный бинарник). Во-вторых, любая модернизация динамической
библиотеки, отражается на всех программах, использующих ее. Таким образом, если неко- торую библиотеку foo используют 10 программ, то исправление какой-нибудь ошибки в foo или любое другое улучшение библиотеки автоматически улучшает все программы, которые используют эту библиотеку. Именно поэтому динамические библиотеки называют совмест- но используемыми. Чтобы применить изменения, внесенные в статическую библиотеку, нужно пересобрать все 10 программ.
В Linux статические библиотеки обычно имеют расширение .a (Archive), а совместно используемые библиотеки имеют расширение .so (Shared Object). Хранятся библиотеки, как правило, в каталогах /lib и /usr/lib. В случае иного расположения (относится только к совместно используемым библиотекам), приходится явно указать путь, чтобы программа запустилась[2].
В динамическую библиотеку вынесена функция, отвечающая за взаимодействие с системой. При компиляции, отдельно собирается библиотека, и отдельно исполняемый файл.
user@host$ g++ -o libparse.so -shared -fPIC -std=c++14 parse.cpp user@host$ g++ main.cpp -L. -lparse -o netmonitor
Теперь простой запуск приложения приведёт к ошибке, т.к. система ожидает наличия файла библиотеки в строго определённом месте.
user@host$ ./netmonitor
./netmonitor: error while loading shared libraries: libparse.so: cannot open shared user@host$
Отсутствие библиотеки можно легко обнаружить при запуске утилиты ldd (строка 2, листинг 6).
Листинг 6: Демонстрация работы программы ldd для приложения, использующего дина- мическую библиотеку
1
2
3
4
5
6
7
Эту проблему можно обойти если явным образом перед запуском программы передать путь к библиотеке через параметры
user@host$ LD_LIBRARY_PATH=. ./netmonitor enp2s0 enp2s0:
Receive 9686554269 bytes (6645253 packets)
Transmit 645757402 bytes (3625776 packets) user@host$
Из результатов анализа распределения памяти можно сделать вывод о том, что при запуске программы ей выделяется свободное место в памяти, в следствии чего адреса, по которым располагаются точкивхода или подключения меняются при повторных запусках,однако, состав, порядок и смещения загружаемыхмодулей относительно начального адреса в выделенной памяти не изменяется.
studfiles.net
DLL-библиотеки содержат программы общего пользования, т. е. фактически подпрограммы, используемые многими (или всеми) загружаемыми приложениями. При обычной, не динамической компоновке все подпрограммы, в которых нуждается данное приложение, подсоединяются к основной программе и входят в состав ее выполнимого файла. Если некоторая подпрограмма нужна многим приложениям, то ее коды размножаются, повторяясь во всех скомпонованных приложениях. Такая система приводит к увеличению объемов загрузочных файлов и крайне неэффективному использованию памяти компьютера.
Суть использования DLL-библиотек заключается в следующем. Все функцииDLL-библиотек находятся в памяти в одном экземпляре. При компоновке приложения в его загрузочный файл включаются не коды требуемых функций, а лишь их имена вместе с именами содержащих ихDLL-библиотек. В процессе загрузки приложения в память система проецирует кодыDLLна адресное пространство выполняемого процесса. В этом случае связь приложения сDLL-библиотекой сохраняется на все время выполнения приложения; такая процедура носит название неявного или статического подключения.
В целях оптимизации используемых ресурсов приложение может пойти дальше, организовав загрузку библиотеки (фактически проецирование DLLна свое адресное пространство) в нужный момент по ходу своего выполнения. Когда необходимость в функцияхDLLотпадет, приложение может выгрузить библиотеку, освободив свое адресное пространство. Такая процедура носит название динамического подключения (динамической загрузки).
Необходимость разработки прикладных DLL-библиотек возникает в тех случаях, когда в сложном программном комплексе, включающем в себя много отдельных программ (например, приема, обработки и сохранения данных, их графического отображения в разных видах и т. д.) какие-то его элементы имеют общий характер и должны использоваться многими составляющими комплекса. Оформление этих элементов в виде функцийDLL-библиотек позволяет сократить объем программного обеспечения и повысить эффективность его функционирования.
Создание собственной DLL-библиотеки не составляет особого труда. Современные интегрированные среды разработки (BorlandC++,MicrosoftVisualStudioи др.) имеют в своем составе средства подготовки как обычных выполнимых программ, так и библиотек динамической компоновки. Фактически оформление некоторой прикладной функции в виде элементаDLL-библиотеки сводится к установке соответствующих флажков при создании проекта, в котором данная функция будет компилироваться.
Статическое подключение DLL-библиотеки к приложению осуществляется также на этапе создание проекта, в котором компилируется и отлаживается данное приложение. Динамическое же подключение требует включения в текст приложения функций загрузки и выгрузкиDLL-библиотеки.
Техника создания и использования прикладных DLL-библиотек описана в соответствующих лабораторных работах данного пособия.
studfiles.net
Использование динамических библиотек (по-другому — библиотек динамической
компоновки) — это способ осуществления модульности в период выполнения
программы. Динамическая библиотека (Dynamic Link Library - DLL
)
позволяет упростить и саму разработку программного обеспечения. Вместо того
чтобы каждый раз перекомпилировать огромные ЕХЕ-программы, достаточно
перекомпилировать лишь отдельный динамический модуль. Кроме того, доступ к
динамической библиотеке возможен сразу из нескольких исполняемых модулей, что
делает многозадачность более гибкой. Структуре исполняемых модулей будет
посвящена отдельная глава, но уже сейчас могу сказать, что структура DLL-модуля
практически такая же, как и ЕХЕ-модуля. Тот, кто программировал под MS DOS,
должен быть знаком с понятием оверлея. По своей функциональности динамическая
библиотека очень похожа на оверлей, но название «динамическая библиотека» более
удачно42.
При написании ЕХЕ-модулей Вы уже познакомились с тем, как определять
импортируемые функции. Достаточно объявить эти функции как EXTERN
.
При создании динамической библиотеки Вам придется указывать и импортируемые, и
экспортируемые функции.
Для того чтобы двигаться дальше, введу такое понятие, как связывание.
Собственно, я уже ввел это понятие, когда рассматривал работу редактора связей.
Во время трансляции связываются имена, указанные в
программе как внешние, (EXTERN
) с соответствующими именами из
библиотек, которые указываются при помощи директивы IMPORTLIB
.
Такое связывание называется ранним (или статическим).
Напротив, в случае с динамической библиотекой связывание происходит во время
выполнения модуля. Такое связывание называется поздним (или
динамическим). При этом позднее связывание может происходить в автоматическом
режиме в начале запуска программы и при помощи специальных API-функций (см.
ниже), по желанию программиста. При этом говорят о явном и неявном связывании.
Сказанное иллюстрирует Рис. 3.3.1. Заметим также, что использование динамической
библиотеки экономит дисковое пространство, т.к. представленная в библиотеке
процедура содержится лишь один раз, в отличие от процедур, помещаемых в модули
из статических библиотек43.
В среде Windows практикуются два механизма связывания: по символьным именам и по порядковым номерам. В первом случае функция, определенная в динамической библиотеке, идентифицируется по ее имени, во втором — по порядковому номеру, который должен быть задан при трансляции. Связывание по порядковому номеру в основном практиковалось в старой операционной системе Windows З.х. На наш взгляд, связывание по имени — более удобный механизм.
Рис. 3.3.1. Иллюстрация понятия связывания в ассемблере.
Динамическая библиотека может содержать также ресурсы. Так, файлы шрифтов представляют собой динамические библиотеки, единственным содержимым которых являются ресурсы. Должно сказать, что динамическая библиотека как бы становится продолжением Вашей программы, загружаясь в адресное пространство процесса. Соответственно, данные процесса доступны из динамической библиотеки, и, наоборот, данные динамической библиотеки доступны для процесса.
В любой динамической библиотеке следует определить точку входа (процедура
входа). По умолчанию за точку входа принимают метку, указываемую за директивой
END
(например, END START
). При загрузке динамической
библиотеки и выгрузке динамической библиотеки автоматически вызывается процедура
входа. Заметим при этом, что каким бы способом ни была загружена динамическая
библиотека (явно или неявно), выгрузка динамической библиотеки из памяти будет
происходить автоматически при закрытии процесса или потока. В принципе,
процедура входа может быть использована для некоторой начальной инициализации
переменных. Довольно часто эта процедура остается пустой. При вызове процедуры
входа в нее помещаются три параметра:
Рассмотрим подробнее второй параметр процедуры входа. Вот четыре возможных значения этого параметра:
DLL_PROCESS_DETACH equ 0 DLL_PROCESS_ATTACH equ 1 DLL_THREAD_ATTACH equ 2 DLL_THREAD_DETACH equ 3
DLL_PROCESS_ATTACH
— сообщает, что динамическая библиотека
загружена в адресное пространство вызывающего процесса.
DLL_THREAD_ATTACH
— сообщает, что Текущий процесс создает новый
поток. Такое сообщение посылается всем динамическим библиотекам, загруженным к
этому времени процессом.
DLL_PROCESS_DETACH
— сообщает, что динамическая библиотека
выгружается из адресного пространства процесса.
DLL_THREAD_DETACH
— сообщает, что некий поток, созданный данным
процессом, в адресное пространство которого загружена данная динамическая
библиотека, уничтожается.
42 Оверлей (Overlay) в переводе означает перекрытие — указание на то, что в оверлейную область памяти могут загружаться по очереди разные части оверлея, перекрывая друг друга.
43 Вообще говоря, библиотеки, используемые нами
для программирования в Windows, такие как import32.lib
,
user32.lib
и т.п., правильнее называть не статическими
библиотеками, а библиотеками импорта. В них нет программного кода, а лишь
информация, используема для трансляции.
Перейдем теперь к разбору программных примеров динамических библиотек. На
Рис. 3.3.2 приводится пример простейшей динамической библиотеки. Данная
динамическая библиотека, по сути, ничего не делает. Просто при загрузке
библиотеки, ее выгрузки, а также вызове процедуры DLLP1
будет
вызвано обычное Windows-сообщение. Обратите внимание, как определяется процесс
загрузки и выгрузки библиотеки. Заметим также, что процедура входа должна
возвращать ненулевое значение. Процедура DLLP1
обрабатывает также
один параметр, передаваемый через стек обычным способом.
.386P ; плоская модель IFDEF MASM .MODEL FLAT, stdcall ELSE .MODEL FLAT ENDIF PUBLIC DLLP1 ; константы ; сообщения, приходящие при открытии ; динамической библиотеки DLL_PROCESS_DETACH equ 0 DLL_PROCESS_ATTACH equ 1 DLL_THREAD_ATTACH equ 2 DLL_THREAD_DETACH equ 3 IFDEF MASM ; MASM ; прототипы внешних процедур EXTERN MessageBoxA@16:NEAR ; директивы компоновщику для подключения библиотек includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ELSE ; TASM EXTERN MessageBoxA:NEAR MessageBoxA@16 = MessageBoxA includelib c:\tasm32\lib\import32.lib ENDIF ;-------------------------------------------------- ; сегмент данных _DATA SEGMENT DWORD PUBLIC USE32 'DATA' TEXT1 DB 'Вход в библиотеку',0 TEXT2 DB 'Выход из библиотеки',0 MS DB 'Сообщение из библиотеки',0 TEXT DB 'Вызов процедуры из DLL',0 _DATA ENDS ; сегмент кода _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' ; [EBP+10H] ; резервный параметр ; [EBP+0CH] ; причина вызова ; [EBP+8] ; идентификатор DLL-модуля DLLENTRY: MOV EAX,DWORD PTR [EBP+0CH] CMP EAX,0 JNE D1 ; закрытие библиотеки PUSH 0 PUSH OFFSET MS PUSH OFFSET TEXT2 PUSH 0 CALL MessageBoxA@16 JMP _EXIT D1: CMP EAX,1 JNE _EXIT ; открытие библиотеки PUSH 0 PUSH OFFSET MS PUSH OFFSET TEXT1 PUSH 0 CALL MessageBoxA@16 _EXIT: MOV EAX,1 RET 12 ;——————————————————— ; [EBP+8] ; параметр процедуры DLLP1 PROC EXPORT PUSH EBP MOV EBP,ESP CMP DWORD PTR [EBP+8],1 JNE _EX PUSH 0 PUSH OFFSET MS PUSH OFFSET TEXT PUSH 0 CALL MessageBoxA@16 _EX: POP EBP RET 4 DLLP1 ENDP _TEXT ENDS END DLLENTRY
Puc. 3.3.2. Простейшая DLL-библиотека.
Программа на Рис. 3.3.2 может быть оттранслирована как с помощью MASM32, так
и TASM32 (см. ниже). На этом стоит остановиться более подробно. Прежде всего
обратите внимание, что за процедурой, вызываемой из другого модуля, мы указали
ключевое слово EXPORT
. Это слово необходимо для правильной
трансляции в MASM. Для TASM этого не нужно, но, к счастью, этот транслятор
просто не замечает наличия какого-либо слова после PROC
. Зато для
TASM процедура DLLP1
должна быть определена как
PUBLIC
, кроме того, для трансляции в пакете TASM необходимо
подготовить DEF
-файл и указать его в командной строке
TLINK32
. Для создания динамических библиотек в строке link следует
указать ключ /DLL
, а в строке tlink32 -Tpd
(no
умолчанию работает ключ -Tpe
). Ключ /ENTRY:DLLENTRY
в
строке link можно опустить, так как точка входа определяется из директивы
END DLLENTRY
.
Трансляция динамической библиотеки на Рис. 3.3.2.
MASM32.
ml /c /coff /DMASM dll1.asm link /subsystem:windows /DLL /ENTRY:DLLENTRY dll1.objTASM32.
tasm32 /ml dll1.asm tlink32 -aa -Tpd dll1.obj,,,,dll1.defСодержимое dll1.def:
EXPORTS DLLP1
Ниже на Рис. 3.3.3 представлена программа, которая загружает динамическую
библиотеку, показанную на Рис. 3.3.2. Это пример позднего связывания. Библиотека
должна быть вначале загружена при помощи функции LoadLibrary
. Затем
определяется адрес процедуры с помощью функции GetProcAddress
,
после чего можно осуществлять вызов. Как и следовало ожидать, MASM помещает в
динамическую библиотеку вместо DLLP1
имя _DLLP1@0
,
тогда как TASM помещает имя без искажения. Это мы учитываем в нашей программе.
Мы учитываем также возможность ошибки при вызове функций
LoadLibrary
и GetProcAddress
. В этой связи укажем, как
(в какой последовательности) ищет библиотеку функция LoadLibrary
:
GetSystemDirectory
).
GetWindowsDirectory
).
PATH
).В конце программы мы выгружаем из памяти динамическую библиотеку, что, кстати, могли бы и не делать, т.к. по выходе из программы эта процедура выполняется автоматически.
.386P ; плоская модель .MODEL FLAT, stdcall ; константы ; прототипы внешних процедур IFDEF MASM ;MASM EXTERN GetProcAddress@8:NEAR EXTERN LoadLibraryA@4:NEAR EXTERN FreeLibrary@4:NEAR EXTERN ExitProcess@4:NEAR EXTERN MessageBoxA@16:NEAR ; директивы компоновщику для подключения библиотек includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ELSE ; TASM EXTERN GetProcAddress:NEAR EXTERN LoadLibraryA:NEAR EXTERN FreeLibrary:NEAR EXTERN ExitProcess:NEAR EXTERN MessageBoxA:NEAR ; директивы компоновщику для подключения библиотек includelib c:\tasm32\lib\import32.lib GetProcAddress@8 = GetProcAddress LoadLibraryA@4 = LoadLibraryA FreeLibrary@4 = FreeLibrary ExitProcess@4 = ExitProcess MessageBoxA@16 = MessageBoxA ENDIF ;----------------------------------------- ; сегмент данных _DATA SEGMENT DWORD PUBLIC USE32 'DATA' TXT DB 'Ошибка динамической библиотеки',0 MS DB 'Сообщение',0 LIBR DB 'DLL1.DLL',0 HLIB DD ? IFDEF MASM NAMEPROC DB '_DLLP1@0',0 ELSE NAMEPROC DB 'DLLP1',0 ENDIF _DATA ENDS ; сегмент кода _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ; загрузить библиотеку PUSH OFFSET LIBR CALL LoadLibraryA@4 CMP EAX,0 JE _ERR MOV HLIB,EAX ; получить адрес процедуры PUSH OFFSET NAMEPROC PUSH HLIB CALL GetProcAddress@8 CMP EAX,0 JNE YES_NAME ; сообщение об ошибке _ERR: PUSH 0 PUSH OFFSET MS PUSH OFFSET TXT PUSH 0 CALL MessageBoxA@16 JMP _EXIT YES_NAME: PUSH 1 ; параметр CALL EAX ; закрыть библиотеку PUSH HLIB CALL FreeLibrary@4 ; библиотека автоматически закрывается также ; при выходе из программы ; выход _EXIT: PUSH 0 CALL ExitProcess@4 _TEXT ENDS END STARTРис. 3.3.3. Вызов динамической библиотеки. Явное связывание.
onbooks.ucoz.ru
31.01.2015: Пессимизация. Что это такое и как избежать?
28.01.2015: 5 инструментов продвижения, которые больше не работают
26.01.2015: Простой способ прогнозировать посещаемость сайта
23.01.2015: Что такое верстка сайта и ее виды
21.01.2015: Объем контента сайта и его влияние на позиции в поисковой выдаче
Все публикации >>>
Все комментарии >>>
xbb.uz