Prelink

From Gentoo Wiki
Jump to: navigation, search
This page is a translated version of the page Prelink and the translation is 100% complete.

Other languages:
English • ‎français • ‎italiano • ‎русский • ‎日本語 • ‎한국어

В этом руководстве рассказывается, как использовать поддержку prelink в Portage 2.0.46 и более поздних версиях.

Contents

Введение

Что такое Prelink и как он может помочь?

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

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

Предварительное связывание может сократить время запуска приложений. Например, типичное время загрузки программы KDE можно сократить на целых 50%. Единственное, что необходимо сделать - повторно выполненить prelink каждый раз, когда библиотека обновляется для предварительно связанного исполняемого файла.

Предупреждение
Prelink не будет работать с Hardened Gentoo. Это связано с тем, что оба проекта пытаются изменить отображение адресного пространства разделяемых библиотек. Но prelink с опцией -R рандомизирует базовые адреса библиотеки, обеспечивая некоторую степень усиленной защиты.

Обобщение

  • Предварительное связывание осуществляется с помощью программы, которая, как ни странно, называется prelink. Она изменяет бинарный файл, чтобы ускорить его запуск.
  • Если зависящие от приложения библиотеки меняются после того, как вы подвергли его предварительному связыванию, вам нужно повторно связать приложение, иначе вы потеряете выгоду в скорости. Это означает, что каждый раз, когда вы обновляете через portage пакет, который обновляет библиотеки, они должны быть повторно подвергнуты процессу предварительного связывания.
  • Изменение бинарного файла полностью обратимо. У prelink есть функция возврата к предыдущему состоянию.
  • Текущие версии Portage могут обрабатывать с помощью prelink изменения MD5sums и mtimes бинарных файлов.
  • Вам не нужно устанавливать FEATURES="prelink" в вашем файле make.conf; Portage автоматически будет поддерживать prelink, если он находит бинарный файл prelink.

Настройка Prelink

Установка программ

Сначала вам нужно установить утилиту prelink. Процесс emerge автоматически проверяет, может ли ваша система безопасно использовать предварительное связывание.

root #emerge --ask prelink

Ряд людей получают ошибки в при установке prelink из-за неудавшихся тестов. Тесты были введены из соображений безопасности, поведение prelink не предсказуемо, если вы отключите их. Ошибки emerge обычно зависят только от основных пакетов; Binutils, gcc и glibc. Попробуйте повторно пересобрать эти пакеты в этом случае.

Заметка
Совет: если вы получаете ошибку, попробуйте собрать и протестировать prelink самостоятельно (./configure; make; make check). При сбое, вы можете просмотреть файлы *.log в каталоге testsuite. Они могут предоставить вам полезные подсказки.

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

Подготовка системы

Также убедитесь, что вы "не" установили -fPIC в «CFLAGS/CXXFLAGS». Если вы это сделали, вам нужно будет полностью пересобрать всю систему без него.

Конфигурация

Запуск env-update создаст файл /etc/prelink.conf, который сообщает prelink, какие файлы должны быть предварительно связаны.

root #env-update

К сожалению, вы не можете предварительно связать файлы, которые были скомпилированы старыми версиями binutils. Большинство таких приложений поставляются только в виде предварительно скомпилированных бинарных пакетов, которые установлены в /opt. Создание следующего файла укажет prelink не пытаться связать их.

Файл /etc/env.d/60prelink
PRELINK_PATH_MASK="/opt"
Заметка
Вы можете добавить больше или меньше каталогов в виде разделенного двоеточиями списка.

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

Использование Prelink

Я использую следующую команду для связывания всех двоичных файлов в каталогах, заданных /etc/prelink.conf.

root #prelink -amR
Предупреждение
Было замечено, что если вы располагаете маленьким количеством свободного места на диске и вы подвергаете предварительному связыванию всю свою систему, существует вероятность того, что ваши двоичные файлы могут быть усечены. В результате вы получите сломанную систему. Используйте команду file или readelf, чтобы проверить состояние двоичного файла. Кроме того, заранее проверьте количество свободного места на жестком диске с помощью df -h.
Разъяснение параметров:
-a "All": Предварительное связывание для всех бинарных файлов
-m Сохранить пространство виртуальной памяти. Это необходимо, если у вас много библиотек, которые должны быть предварительно связаны.
-R Random -- Рандомизировать порядок адресов, это повышает безопасность при ошибках переполнения буфера.
Заметка
Дополнительные опции и подробности смотрите в man prelink.

Задание Cron для Prelink

Установите sys-devel/prelink-20060213, а затем установите задание cron в /etc/cron.daily/prelink. Чтобы включить его, отредактируйте файл конфигурации /etc/conf.d/prelink. Он будет запускать prelink ежедневно в фоновом режиме, спасая вас от необходимости запуска команды вручную.

Ускорение KDE после предварительного связывания

Время загрузки KDE может быть значительно уменьшено после предварительного связывания. Если вы сообщите KDE, что он был предварительно связан, это отключит загрузку kdeinit (поскольку он больше не требуется), что еще больше ускорит KDE.

Установите KDE_IS_PRELINKED=1 в /etc/env.d/*kdepaths*, чтобы сообщить KDE о предварительном связывании.

Удаление prelink

Если вы передумаете использовать предварительное связывание, прежде чем удалять prelink, сначала нужно удалить prelink cronjob из /etc/cron.daily и /etc/conf.d/prelink. Затем вам придется удалить предварительное связывание из всех двоичных файлов:

root #prelink -au

Наконец, удалите сам пакет prelink:

root #emerge -c prelink

Известные проблемы и их решения

"Cannot prelink against non-PIC shared library" ("Невозможно осуществить предварительное связывание с не-PIC-разделяемой библиотекой")

Причина этой проблемы связана с плохо скомпилированными разделяемыми библиотеками, которые были скомпилированы без gcc опции -fPIC для всех их объектных файлов.

Библиотеки, которые не были исправлены или не могут быть исправлены:

  • Библиотеки в wine пакете, включая winex. Предварительное связывание в любом случае не ускорит выполнение исполняемых файлов MS Windows.
  • Библиотека в media-video/mjpegtools, /usr/lib/liblavfile-1.6.so.0.
  • Библиотеки Nvidia OpenGl, /usr/lib/opengl/nvidia/lib/libGL.so.*. Из соображенияй производительности они были скомпилированы без поддержки PIC.

Если ваша проблемная библиотека не указана в списке, пожалуйста, сообщите об этом, желательно в виде patch'а добавив -fPIC в соответствующие CFLAGS.

Когда я применяю предварительное связывание к моей системе, некоторые статические двоичные файлы больше не работают

Когда дело касается glibc, нет такого понятия, как 100% статический двоичный файл. Если вы статически компилируете двоичный файл с помощью glibc, он все равно может зависеть от других системных файлов. Ниже приводится объяснение Дика Хауэлла (Dick Howell),

"Полагаю, идея состоит в том, что все должно находиться в загруженном файле, поэтому ничего не зависит от локальных библиотек целевой системы. К сожалению, в случае с Linux, и я думаю, с чем бы то ни было, что использует GLIBC, это не совсем так. Возьмем к примеру «libnss» (переключатель службы имен, некоторые люди называют его cbcntvjq сетевой системой безопасности), которая предоставляет функции для доступа к различным базам данных для аутентификации, сетевой информации и других вещей. Предполагается, что прикладные программы не зависят от отдельно настроенного реального сетевого окружения машины. Хорошая идея, но изменения в GLIBC могут привести к проблемам при ее загрузке. И вы не можете статически связать «libnss», поскольку она настроена для каждой машины отдельно. Проблема возникает, я думаю, в основном из-за статического связывания других GLIBC библиотек, в частности «libpthread», «libm» и «libc», из которых происходят несовместимые вызовы функций «libnss»."

Prelink прерывается с "prelink: dso.c: 306: fdopen_dso: Assertion 'j == k' failed."

Это известная проблема, любезно диагностированная здесь. Prelink не может справиться с UPX-сжатыми исполняемыми файлами. Начиная с prelink-20021213, нет способа это исправить, кроме как скрыть исполняемые файлы во время предварительного связывания. Смотрите раздел выше для простого способа сделать это.

Я использую grsecurity, и кажется, что предварительное связывание не работает.

Чтобы предварительно связать систему с grsecurity с использованием рандомизированной базы mmap(), необходимо включить параметр «randomized mmap() base» OFF для /lib/ld-2.3.*.so. Это можно сделать с помощью утилиты chpax, но это необходимо сделать, когда файл не используется (например, загрузиться с компакт-диска для восстановления).

Prelink падает с ошибкой "prelink: Can't walk directory tree XXXX: Too many levels of symbolic links" ("prelink: не удается обойти дерево каталогов XXXX: слишком много уровней символических ссылок")

Ваши символьные ссылки вложены слишком глубоко. Это происходит, когда символьная ссылка указывает на себя. Например, наиболее распространенным является /usr/lib/lib -> lib. Чтобы это исправить, вы можете найти символьную ссылку вручную или использовать утилиту, предоставленную пакетом symlinks:

root #emerge symlinks
root #symlinks -drv /

Более подробную информацию можно найти в Bugzilla и в этом сообщении на Форуме.

Заключение

Предварительное связывание может значительно ускорить время запуска для ряда крупных приложений. Его поддержка встроена в Portage. Также предварительное связывание безопасно, так как вы всегда сможете его отменить для любого двоичного файла при возникновении проблем. Просто помните, что при обновлении glibc или других библиотек, с которыми вы произвели предварительное связывание, вам нужно повторно запустить prelink! Короче, удачи!


This page is based on a document formerly found on our main website gentoo.org.
The following people contributed to the original document: Stefan Jones, John P. Davis, Jorge Paulo, Erwin, nightmorph
They are listed here because wiki history does not allow for any external attribution. If you edit the wiki article, please do not add yourself here; your contributions are recorded on each article's associated history page.