Разделяемая библиотека. Создание и установка разделяемых библиотек (shared libraries) в Linux


Большинство современных версий Unix поддерживают разделяемые библиотеки. Разделяемые библиотеки позволяют изъять из исполняемого файла библиотечные функции; в результате в памяти системы хранится единственная копия библиотеки, к которой обращаются все процессы. Это заметно уменьшает размер исполняемых файлов, но может несколько увеличить нагрузку, когда приложение запускается в первый раз или когда происходит первое обращение к библиотечной функции. Еще одно преимущество разделяемых библиотек заключается в том, что при обновлении библиотеки не требуется исправлять связи с библиотекой в каждой программе, которая использует эту библиотеку. (Здесь мы исходим из предположения, что количество и типы аргументов библиотечных функций не изменились).

ОС Linux предоставляет возможность указать компилятору cc , следует ли использовать разделяемые библиотеки в программе или нет.

7.7. Распределение памяти

Стандарт ISO C определяет три функции, с помощью которых производится распределение памяти:

    Функция malloc выделяет заданное количество байтов памяти. Выделенный объем памяти не очищается.

    Функция calloc выделяет пространство для заданного количества объектов определенного размера. Выделенный объем памяти заполняется нулевыми байтами.

    Функция realloc перераспределяет выделенную ранее память, увеличивая или уменьшая ее объем. Увеличение выделенного ранее объема может сопровождаться перемещением участка памяти в новое место. Кроме того, участок памяти, который оказывается между концом ранее выделенного блока и новым концом, не инициализируется.

#include

void *malloc (size_t size);

void *calloc (size_t nobj, size_t size);

void *realloc (void *ptr, size_t newsize);

/* все три функции возвращают непустой указатель в случае успеха, NULL – в случае ошибки */

void free (void *ptr);

Эти три функции гарантируют возврат указателей, которые будут иметь выравнивание, подходящее для хранения объектов данных любого типа. Например, если ограничение для конкретной системы состоит в том, что объекты типа double должны размещаться по адресам, кратным числу 8, то все указатели, возвращаемые этими функциями, будут содержать адреса, кратные 8.

Все три функции возвращают нетипизированный указатель void * , поэтому, подключив к программе заголовочный файл , который содержит прототипы функций, мы не должны выполнять явное приведение типов при присваивании значений функций типизированным указателям.

Функция free освобождает выделенную ранее память, на которую указывает аргумент ptr . Освобожденное пространство, как правило, помещается в пул свободной памяти и может быть снова распределено при последующем обращении к одной из трех функций.

Функция realloc позволяет увеличивать или уменьшать размер ранее выделенной области памяти. Например, если мы выделяем участок памяти для массива из 512 элементов и затем в процессе его заполнения вдруг обнаруживаем, что нам потребуется память для хранения более 512 элементов, то мы можем вызвать функцию realloc . В этом случае, если позади выделенной ранее области имеется блок свободной памяти достаточного объема, функция realloc ничего никуда не перемещает. Она просто добавляет область требуемого объема в конец и возвращает тот же самый указатель, который был ей передан. Однако если позади выделенной ранее области нет свободного участка памяти, функция realloc находит другую область памяти достаточного объема и копирует содержимое существующего массива из 512 элементов в новое место, после чего освобождает старую область памяти и возвращает указатель на новую область. Поскольку ранее выделенная область памяти может быть перемещена, мы не должны использовать другие указатели на эту область после вызова функции realloc .

Обратите внимание, что последний аргумент функции realloc определяет новый размер требуемой области, а не разницу между новым и старым размерами. В особом случае, когда в аргументе ptr передается пустой указатель, функция realloc ведет себя подобно функции malloc , выделяя область памяти размером newsize .

Функции распределения памяти обычно реализуются на основе системного вызова sbrk . Этот системный вызов расширяет (или усекает) область динамической памяти (кучи) процесса (рис. 7.3). Пример типичной реализации функций malloc и free приводится в разделе 8.7 [Керниган, Ритчи].

Хотя системный вызов sbrk может как увеличивать, так и уменьшать объем памяти процесса, большинство версий malloc и free никогда не уменьшают его. Освобождаемое пространство становится доступным для последующего распределения, и, как правило, не возвращается ядру – оно помещается в пул свободной памяти функции malloc .

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

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

Другие возможные ошибки, которые могут оказаться фатальными – попытка освобождения блока памяти, уже освобожденного ранее, а также передача функции free указателя, который не был получен от одной из трех функций выделения памяти. Если процесс вызывает функцию malloc , но забывает вызвать функцию free , то объем используемой памяти начинает непрерывно увеличиваться; это называют утечкой памяти. Если процесс не будет возвращать ставшие ненужными блоки памяти с помощью функции free , то объем адресного пространства, занимаемого процессом, будет медленно увеличиваться до тех пор, пока свободное пространство не закончится. Это может привести к снижению производительности системы из-за лишних обращений к файлу подкачки.

Поскольку очень сложно отыскать ошибки, связанные с распределением памяти, некоторые операционные системы (в том числе и ОС Linux) предоставляют версии функций выделения памяти, выполняющие дополнительную проверку наличия ошибок при каждом вызове.

Разделяемая библиотека позволяет использовать содержащиеся в ней символы в нескольких фильмах без копирования этих символов в библиотеки фильмов. Из-за этого объекты разделяемой библиотеки называются ресурсами (Assets). При этом разделяемая библиотека используется как внешний файл и не добавляется к создаваемому (или редактируемому) фильму.

Применение разделяемых библиотек целесообразно, например, в следующих случаях:

  • при использовании одного и того же звукового сопровождения на нескольких страницах сайта;
  • при совместном использовании текстовых символов шрифта на нескольких страницах сайта;
  • когда требуется обеспечить единый источник для элементов анимации, используемой в нескольких сценах фильма или в нескольких фильмах;
  • когда требуется иметь центральную библиотеку ресурсов, чтобы упростить контроль за вносимыми изменениями.

Flash MX поддерживает два типа разделяемых библиотек:

  • Run-time - разделяемая библиотека времени выполнения; символы, входящие в такую библиотеку, доступны для совместного использования несколькими фильмами, однако редактироваться такие символы могут только непосредственно в фильме-источнике;
  • Author-time - библиотека, разделяемая на время разработки; символы, входящие в такую библиотеку, доступны для совместного использования несколькими фильмами, причем разрешается редактировать содержимое библиотеки в любом фильме-совладельце.

Чтобы ресурсы разделяемой библиотеки могли быть доступны в фильмах, размещенных на удаленном сайте, Flash-файл с этой библиотекой должен быть экспортирован в формат SWF и загружен на Web-сайт.

Замечание
В предыдущей версии Flash поддерживается только разделяемая библиотека времени выполнения
.

Чтобы создать разделяемую библиотеку типа Run-time , необходимо:

  1. Определить ее ресурсы (входящие в нее символы) в отдельном фильме.
  2. Разрешить экспорт разделяемых символов.
  3. Указать URL сайта, на котором будет размещена библиотека.
  4. Экспортировать Flash-файл с этой библиотекой в формат SWF и выгрузить на Web-сайт.

Чтобы получить возможность использовать символы разделяемой библиотеки Run-time в других фильмах ("совладельцах"), необходимо в каждом из них создать ссылку на разделяемые символы.

Теперь рассмотрим перечисленные выше шаги более подробно.

После создании разделяемой библиотеки необходимо указать, какие включенные в нее символы могут быть экспортированы в другие фильмы. Для этого требуется выполнить следующие действия:

  1. Выберите в списке символ, который вы хотите сделать "разделяемым".
  2. В контекстном меню символа выберите команду Linking (Связывание).
  3. В открывшемся диалоговом окне Symbol Linkage Properties (Параметры связывания символа), рис. 10.12, установите флажок Export for runtime sharing (Разрешить экспорт на время выполнения).
  4. В текстовом поле Identifier введите имя (идентификатор) символа, под которым он будет экспортирован в фильм-совладелец; хотя по умолчанию в поле заносится библиотечное имя символа, если оно содержит пробелы, удалите их.
  5. В текстовом поле URL введите интернет-адрес фильма-источника (то есть SWF-файла с разделяемой библиотекой).
  6. Если экспортируемый символ следует использовать непосредственно с первого кадра фильма-совладельца, установите флажок Export in first frame .
  7. Если экспортируемый символ следует сделать доступным в сценарии на ActionScript, установите флажок Export for ActionScript .

Рис. 10.12 . Диалоговое окно установки параметров символов разделяемой библиотеки

Чтобы использовать ресурсы разделяемой библиотеки Run-time в фильме-совладельце, требуется выполнить следующие действия:

  1. Откройте библиотеку этого фильма, выбрав в меню Window команду Library .
  2. В раскрывающемся меню библиотеки выберите команду New Symbol; в результате на экране появится диалоговое окно Create New Symbol (Создание нового символа), центральная часть которого аналогична по формату диалоговому окну Symbol Linkage Properties (рис. 10.13).
  3. В текстовом поле Identifier введите имя символа, который следует импортировать в фильм-совладелец.
  4. В текстовом поле URL введите интернет-адрес фильма-источника.


Рис. 10.13 . Диалоговое окно для установки параметров разделяемого символа

Разделяемая библиотека позволяет использовать содержащиеся в ней символы в нескольких фильмах без копирования этих символов в библиотеки фильмов. Из-за этого объекты разделяемой библиотеки называются ресурсами (Assets). При этом разделяемая библиотека используется как внешний файл и не добавляется к создаваемому (или редактируемому) фильму.

Применение разделяемых библиотек целесообразно, например, в следующих случаях:

  • при использовании одного и того же звукового сопровождения на нескольких страницах сайта;
  • при совместном использовании текстовых символов шрифта на нескольких страницах сайта;
  • когда требуется обеспечить единый источник для элементов анимации, используемой в нескольких сценах фильма или в нескольких фильмах;
  • когда требуется иметь центральную библиотеку ресурсов, чтобы упростить контроль за вносимыми изменениями.

Flash MX поддерживает два типа разделяемых библиотек:

  • Run-time - разделяемая библиотека времени выполнения; символы, входящие в такую библиотеку, доступны для совместного использования несколькими фильмами, однако редактироваться такие символы могут только непосредственно в фильме-источнике;
  • Author-time - библиотека, разделяемая на время разработки; символы, входящие в такую библиотеку, доступны для совместного использования несколькими фильмами, причем разрешается редактировать содержимое библиотеки в любом фильме-совладельце.

Чтобы ресурсы разделяемой библиотеки могли быть доступны в фильмах, размещенных на удаленном сайте, Flash-файл с этой библиотекой должен быть экспортирован в формат SWF и загружен на Web-сайт.

Замечание

В предыдущей версии Flash поддерживается только разделяемая библиотека времени выполнения.

Чтобы создать разделяемую библиотеку типа Run-time, необходимо:

  1. Определить ее ресурсы (входящие в нее символы) в отдельном фильме.
  2. Разрешить экспорт разделяемых символов.
  3. Указать URL сайта, на котором будет размещена библиотека.
  4. Экспортировать Flash-файл с этой библиотекой в формат SWF и выгрузить на Web-сайт.

Чтобы получить возможность использовать символы разделяемой библиотеки Run-time в других фильмах («совладельцах»), необходимо в каждом из них создать ссылку на разделяемые символы.

Теперь рассмотрим перечисленные выше шаги более подробно.

После создании разделяемой библиотеки необходимо указать, какие включенные в нее символы могут быть экспортированы в другие фильмы. Для этого требуется выполнить следующие действия:

  1. Выберите в списке символ, который вы хотите сделать «разделяемым».
  2. В контекстном меню символа выберите команду Linking (Связывание).
  3. В открывшемся диалоговом окне Symbol Linkage Properties (Параметры связывания символа), рис. 10.12, установите флажок Export for runtime sharing (Разрешить экспорт на время выполнения).
  4. В текстовом поле Identifier введите имя (идентификатор) символа, под которым он будет экспортирован в фильм-совладелец; хотя по умолчанию в поле заносится библиотечное имя символа, если оно содержит пробелы, удалите их.
  5. В текстовом поле URL введите интернет-адрес фильма-источника (то есть SWF-файла с разделяемой библиотекой).
  6. Если экспортируемый символ следует использовать непосредственно с первого кадра фильма-совладельца, установите флажок Export in first frame.
  7. Если экспортируемый символ следует сделать доступным в сценарии на ActionScript, установите флажок Export for ActionScript.

Рис. 10.12. Диалоговое окно установки параметров символов разделяемой библиотеки

Чтобы использовать ресурсы разделяемой библиотеки Run-time в фильме-совладельце, требуется выполнить следующие действия:

  1. Откройте библиотеку этого фильма, выбрав в меню Window команду Library.
  2. В раскрывающемся меню библиотеки выберите команду New Symbol; в результате на экране появится диалоговое окно Create New Symbol (Создание нового символа), центральная часть которого аналогична по формату диалоговому окну Symbol Linkage Properties (рис. 10.13).
  3. В текстовом поле Identifier введите имя символа, который следует импортировать в фильм-совладелец.
  4. В текстовом поле URL введите интернет-адрес фильма-источника.

Рис. 10.13. Диалоговое окно для установки параметров разделяемого символа

Применение разделяемой библиотеки другого типа - Author-time - позволяет изменять (точнее, заменять) содержимое символов в редактируемом FLA-файле. При этом следует иметь в виду, что имя символа уже «зашито» в редактируемом фильме. Поэтому символ, импортируемый из разделяемой библиотеки, как бы подменяет собой исходный символ, сохраняя его имя. Если импортируемый символ содержит вложенные символы, они также будут импортированы.

Чтобы связать символ, подлежащий «подмене», с соответствующим символом из разделяемой библиотеки, необходимо:

  1. В редактируемом файле откройте окно библиотеки, выбрав в меню Window команду Library.
  2. В списке символов выберите символ, подлежащий «подмене», щелкните на нем правой кнопкой и в контекстном меню выберите команду Properties.
  3. В нижней части открывшегося диалогового окна. (см. рис. 10.13), в группе элементов Source (Источник) щелкните на кнопке Browse (Просмотр), и в окне Window Explorer выберите FLA-файл с нужной библиотекой; в результате на экране появится еще одно окно - Select Source Symbol (Выбор символа-источника), которое содержит список всех символов разделяемой библиотеки (рис. 10.14).


Рис. 10.14. Диалоговое окно Select Source Symbol

  1. Выберите в списке нужный символ и щелкните на кнопке ОК; это приведет к закрытию окна и изменению формата элементов управления в группе Source (рис. 10.15):
    • станет доступен флажок Always update before publishing (Всегда обновлять перед публикацией) - если он установлен, то символ в редактируемом фильме будет автоматически заменяться символом из разделяемой библиотеки при публикации фильма;
    • в текстовом поле File появится путь к файлу с разделяемой библиотекой;
    • в текстовом поле Symbol Name появится имя символа из разделяемой библиотеки;
    • станет доступна кнопка Symbol, щелчок на которой открывает диалоговое окно Select Source Symbol, приведенное на рис. 10.14.


Рис. 10.15. Формат элементов управления в группе Source после связывания символов

Замечание

Фильм может использовать ресурсы нескольких разделяемых библиотек любого типа.

В завершение приведем еще один способ, позволяющий воспользоваться содержимым библиотеки другого фильма. Для этого необходимо:

  1. Выбрать в меню File (Файл) основного окна Flash команду Open As Library (Открыть как библиотеку).
  2. С помощью окна Windows Explorer указать Flash-файл с нужной библиотекой; в результате на столе будет открыто окно этой библиотеки.
  3. Скопировать нужные символы из окна библиотеки в библиотеку фильма (или непосредственно на стол).

Содержимое такой библиотеки, подобно содержимому общей и постоянной библиотек, не может быть изменено из фильма-клиента (то есть из фильма, использующего ее ресурсы).

Статические и динамические библиотеки.

Библиотеками называют «сборники» подпрограмм или объектов, как правило, ориентированных на решение набора близких по тематике задач. С точки зрения их организации и использования библиотеки бывают статическими и динамическими.

Статические библиотеки (static library) могут представлять собой набор исходных кодов, подключаемых программистом в свою программу, либо в виде заранее скомпилированных объектных файлов, связываемых вместе на этапе компиляции. В Windows такие файлы обычно имеют расширение <.lib>. В результате связывания со статической библиотекой, программа включает все используемые ей функции, что увеличивает её размер, но делает более автономной.

Динамические библиотеки (shared library, dynamic link library) загружаются операционной системой по «требованию» запущенной программы уже в ходе её выполнения. Если необходимая библиотека уже была загружена в память, то повторная загрузка не выполняется. При этом один и тот же набор функций или объектов библиотеки может быть использован одновременно несколькими работающими программами, что позволяет эффективно использовать ресурсы оперативной памяти. Динамические библиотеки в Windows обычно имеют расширение <.dll>.

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

Создание динамической библиотеки.

В Microsoft Visual Studio создание проекта для построения динамической библиотеки аналогично привычной процедуре создания проекта косольного приложения. Тип проекта Win32 Console Application, только теперь в мастере создания проекта нужно быдет выбрать пункт «DLL»:

В случае, если такой пункт в мастере отсутствует, можно создать обычный проект Console Application, а затем в свойствах проекта задать его тип:

Configuration Properties => General => Configuration Type: Dynamic Library (.dll)

Declspec(dllexport) void display(const char * str);

#include "dlltest.h"

void display(const char * str)

Модификатор __declspec(dllexport) разрешает экспорт библиотекой указанной функции для использования её другими приложениями.

В результате сборки проекта будет создан файл динамической библиотеки с расширением <.dll>, а также файл библиотеки импорта с расширением <.lib>. Библиотека импорта предназначена для облегчения последующего использования динамической библиотеки. Несмотря на то, что расширение файла библиотеки импорта совпадает со стандартным расширением статических библиотек, путать их не стоит.

Использование динамической библиотеки.

Использовать динамическую библиотеку в программе можно двумя способами. Неявное связывание подразумевает использование библиотеки импорта для определения адресов функций, предоставляемых библиотекой. Операционная система загружает библиотеку DLL после загрузки исполняемого файла программы. Исполняемый файл вызывает экспортированные функции библиотеки DLL таким способом, как если бы функции содержались в самом исполняемом файле.

При явном связывании исполняемый файл, использующий библиотеку DLL, должен делать вызовы функции для явной загрузки и выгрузки библиотеки DLL и осуществления доступа к экспортированным функциям библиотеки DLL. Клиентский исполняемый файл вызывает экспортированные функции с помощью указателя функции.

Независимо от выбранного метода исполняемый файл может использовать одну и туже библиотеку DLL. Более того, эти механизмы не являются взаимоисключающими, поскольку в то время как один исполняемый файл неявно связывается с библиотекой DLL, другой может выполнять явное связывание.

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

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

    Подключить соответствующий заголовочный файл “dlltest.h”. Для этого нужно либо использовать путь к файлу непосредственно в директиве #include (если проекты находятся в одной папке решения, то лучше использовать относительный путь), либо в свойствах проекта добавить путь к этому заголовочному файлу в разделе

Configuration Parameters => C/C++ => General => Additional Include Directories

    Использовать файл соответствующей библиотеки импорта. Для этого можно воспользоваться директивой вида (здесь использован относительный путь к построенному lib-файлу).

Кроме того, можно добавить путь к файлу библиотеки импорта в свойствах проекта в разделе

Configuration Parameters => Linker => Input => Additional Dependencies

Теперь создадим основной файл программы с таким содержимым:

#pragma comment(lib, "../Debug/dlltest.lib")

#include "dlltest.h"

display("Hello");

system("pause");

Для успешного запуска программы осталось только обеспечить доступность соответствующей DLL библиотеки. При запуске программы операционная система будет искать все требуемые файлы библиотек в папке, откуда была запущена программа, а также в системных путях, определеннных переменной окружения PATH. Соответственно, DLL файл построенной библиотеки должен либо лежать в одной папке вместе с исполняемым файлом вызывающей программы, либо в одной из папок, определенных в PATH.

Знаете ли Вы, что такое мысленный эксперимент, gedanken experiment?
Это несуществующая практика, потусторонний опыт, воображение того, чего нет на самом деле. Мысленные эксперименты подобны снам наяву. Они рождают чудовищ. В отличие от физического эксперимента, который является опытной проверкой гипотез, "мысленный эксперимент" фокуснически подменяет экспериментальную проверку желаемыми, не проверенными на практике выводами, манипулируя логикообразными построениями, реально нарушающими саму логику путем использования недоказанных посылок в качестве доказанных, то есть путем подмены. Таким образом, основной задачей заявителей "мысленных экспериментов" является обман слушателя или читателя путем замены настоящего физического эксперимента его "куклой" - фиктивными рассуждениями под честное слово без самой физической проверки.
Заполнение физики воображаемыми, "мысленными экспериментами" привело к возникновению абсурдной сюрреалистической, спутанно-запутанной картины мира. Настоящий исследователь должен отличать такие "фантики" от настоящих ценностей.

Релятивисты и позитивисты утверждают, что "мысленный эксперимент" весьма полезный интрумент для проверки теорий (также возникающих в нашем уме) на непротиворечивость. В этом они обманывают людей, так как любая проверка может осуществляться только независимым от объекта проверки источником. Сам заявитель гипотезы не может быть проверкой своего же заявления, так как причина самого этого заявления есть отсутствие видимых для заявителя противоречий в заявлении.

Это мы видим на примере СТО и ОТО, превратившихся в своеобразный вид религии, управляющей наукой и общественным мнением. Никакое количество фактов, противоречащих им, не может преодолеть формулу Эйнштейна: "Если факт не соответствует теории - измените факт" (В другом варианте " - Факт не соответствует теории? - Тем хуже для факта").

Максимально, на что может претендовать "мысленный эксперимент" - это только на внутреннюю непротиворечивость гипотезы в рамках собственной, часто отнюдь не истинной логики заявителя. Соответсвие практике это не проверяет. Настоящая проверка может состояться только в действительном физическом эксперименте.

Эксперимент на то и эксперимент, что он есть не изощрение мысли, а проверка мысли. Непротиворечивая внутри себя мысль не может сама себя проверить. Это доказано Куртом Гёделем.







2024 © gtavrl.ru.