Платформы и привязка

Динамическое связывание библиотек Mach-O приносит значительное питание и гибкость к OS X. Посредством динамического связывания платформы могут быть обновлены прозрачно, не требуя, чтобы приложения повторно соединились с ними. Во время выполнения единственная копия кода библиотеки совместно используется среди всех процессов с помощью него, таким образом сокращая использование памяти и улучшая производительность системы.

Динамические совместно используемые библиотеки

Исполняемый код в пакете платформы является динамично соединенной, совместно используемой библиотекой — или, просто, динамической совместно используемой библиотекой. Это - библиотека, код которой может быть совместно использован многократными одновременно рабочими программами.

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

Привязка символа

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

Возможность связать символы во время выполнения сделана возможной внутренней структурой Мужественных динамических совместно используемых библиотек. Модули объектного кода, составляющие библиотеку, создаются для сохранения их отдельных границ; т.е. код от исходных модулей не объединяется в единственный модуль. Во время выполнения редактор динамического канала автоматически загружает и соединяет модули только, поскольку они необходимы. Другими словами, модуль соединяется только, когда программа ссылается на символ в том модуле. Если на символы в определенном модуле не ссылаются, модуль не соединяется.

Рисунок 1 иллюстрирует это “ленивое соединение” поведение. В этом примере, модуле a.o соединяется в программе main подпрограмма, когда библиотечная функция a вызывается. Модуль b.o соединяется когда библиотечная функция b в функции программы doThat вызывается. Модуль c.o никогда не соединяется, потому что никогда не вызывается его функция.

Рисунок 1  Ленивое соединение динамических совместно используемых модулей библиотеки
Lazy linking of dynamic shared library modules

Организация кода платформы

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

При создании платформы необходимо гарантировать, что каждый символ определяется только один раз в библиотеке. Кроме того, «общие» символы не позволяются в библиотеке; необходимо использовать единственное истинное определение и предшествовать всем другим определениям с extern ключевое слово в коде C.

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

Зависимости библиотеки

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

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

Автономные динамические совместно используемые библиотеки

В дополнение к созданию платформ можно создать автономные динамические совместно используемые библиотеки. Условно, автономные динамические совместно используемые библиотеки имеют a .dylib расширение и обычно устанавливается в /usr/lib. Файл библиотеки содержит весь код и ресурсы, необходимые библиотеке.

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

Платформы и предварительная привязка

До OS X v10.3.4, OS X использовал вызванную предварительную привязку функции для устранения задержек времени загрузки, понесенных исполнимыми программами, соединенными с динамическими библиотеками. Предварительная привязка включила предварительное вычисление адресов символа в каждой платформе и библиотеке по системе. Цель этого предварительного вычисления состояла в том, чтобы избежать конфликтов адресного пространства среди библиотек и платформ. Такие конфликты подверглись огромным потерям производительности во время загрузки и заметно замедлят время запуска приложения.

Улучшения динамического загрузчика в OS X v10.3.4 сделали предварительную привязку в основном ненужного. Сам динамический загрузчик был изменен для обработки конфликтов времени загрузки намного более эффективно. Используя новый динамический загрузчик, приложение, не предварительно связывающееся теперь обычно запуски, по крайней мере, как быстро (и иногда быстрее), чем он, сделало на более ранних версиях системы, когда это было предварительно связано.

В OS X v10.4, другое изменение было представлено предобязательному поведению сократить потраченную «оптимизацию» количества времени системы после установки нового программного обеспечения. Вместо того, чтобы предварительно связать все платформы и библиотеки, теперь только выбирают системные платформы, предварительно связываются. Путем выборочного выбора, какие платформы предварительно связываются, предобязательные инструменты в состоянии плотно упаковать наиболее часто используемые платформы системы в меньшее пространство памяти, чем прежде. Этот шаг сокращает сумму пространства, зарезервированного для платформ Apple, и отдает его к сторонним приложениям и платформам.

При разработке платформ для работы версий OS X до 10,4, необходимо все еще позволить предварительно связать и указать предпочтительный адрес. При разработке платформ для OS X v10.4 или позже предварительная привязка не требуется. Предварительная привязка Вашей платформы на более поздних версиях системы не уменьшает производительность, но действительно требует некоторых дополнительных шагов конфигурации, описанных в следующих разделах.

Предварительная привязка Вашей платформы

Если Вы разрабатываете платформу, работающую на OS X v10.4 или ранее, необходимо указать предпочтительный обязательный адрес платформы в проекте XCode.

Следующие шаги показывают Вам, как сконфигурировать предварительную привязку для проекта платформы XCode:

  1. Откройте свой проект в XCode.

  2. В области Groups & Files выберите свою цель, откройте ее окно Info и нажмите Build.

  3. Удостоверьтесь, что Предобязательная установка сборки включена (можно войти prebinding в поле поиска для определения местоположения его).

  4. К Другой установке сборки Флагов Компоновщика добавьте -seg1addr флаг вместе с предпочтительным адресом для Вашей платформы. Например, для установки предпочтительного адреса платформы к 0xb0000000, Вы вошли бы:

    -seg1addr 0xb0000000
  5. Создайте и соедините свою платформу, как обычно.

Когда предобязательные платформы, особенно важно указать предпочтительный адрес с помощью -seg1addr опция. Если Вы позволяете предварительно связать, но не указываете предпочтительный адрес, XCode использует адрес по умолчанию 0x00000000. Это - проблема, потому что тот адрес является также предпочтительным адресом для всех приложений. Вместо этого необходимо установить начальный адрес в область памяти, зарезервированной для использования кодом приложения и платформами. Для списка допустимых диапазонов адресов см. “Предварительную привязку Вашего Приложения” в Инструкциях по Производительности Времени Запуска.

Можно подтвердить предпочтительный адрес платформы путем исследования двоичного файла с помощью otool команда. Посмотрите Нахождение Предпочтительного Адреса Платформы для получения дополнительной информации.

Протесты для предварительной привязки

Если Вы предварительно связываете свою платформу так, чтобы она могла работать на версиях OS X до 10,4, необходимо знать о следующих протестах:

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

  • Ваша платформа не должна содержать ссылки ни на какие неопределенные символы.

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

  • Две платформы (или библиотеки) не могут иметь круговых зависимостей.

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

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

Выбор уникального предпочтительного адреса для Вашей платформы может быть хитрым, особенно если это должно сосуществовать со многими сторонними платформами. Apple обеспечивает ряд допустимых диапазонов для Ваших платформ и приложений для использования. (См. “Предварительную привязку Вашего Приложения” в Инструкциях по Производительности Времени Запуска.) Однако можно все еще столкнуться с областями перекрытия с платформами, разработанными другими группами, любая внутренняя или внешняя часть компания.

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

Нахождение предпочтительного адреса платформы

Для нахождения предпочтительного адреса платформы используйте otool команда с -l опция вывести на экран команды загрузки для двоичного файла платформы. Команды загрузки включают адрес виртуальной памяти, в котором можно загрузить каждый сегмент двоичного файла. Поскольку большинство сегментов находится при смещении с начала библиотеки, необходимо смотреть на начальную букву LC_SEGMENT команда для нахождения предпочтительного базового адреса библиотеки.

Например, предположите, что Вы создаете библиотеку и присваиваете ее предпочтительный адрес 0xb0000000 в Вашем проекте XCode. Выполнение otool -l на Вашей библиотеке из Окна терминала вывел бы на экран начальную команду загрузки, подобную следующему:

Load command 0
      cmd LC_SEGMENT
  cmdsize 328
  segname __TEXT
   vmaddr 0xb0000000
   vmsize 0x00002000
  fileoff 0
 filesize 8192
  maxprot 0x00000007
 initprot 0x00000005
   nsects 4
    flags 0x0

Заметьте значение vmaddr поле. Это поле указывает, что предпочтительный адрес двоичного файла соответствует адрес, который Вы указали в своем проекте XCode.

Платформы Apple и предварительная привязка

В версиях OS X до 10,4, предоставленный Apple платформы поставляются предварительно связанные и присваиваются зарезервированным областям памяти. В OS X v10.4 и позже, системные платформы Apple предварительно связываются динамично при установке операционной системы. В обоих случаях диапазоны памяти, зарезервированные Apple, перечислены в “Предварительной привязке Вашего Приложения” в Инструкциях по Производительности Времени Запуска.