Александр Прокошев
Перекомпиляция ядра и самой операционной системы FreeBSD – часть
непрерывного процесса обеспечения безопасности интернет-сервера, и хотя у
новичка в мире открытых исходников слова «компиляция ядра операционной системы»
обычно вызывают благоговейное преклонение перед произносящим их, этот процесс
на самом деле не является слишком сложным и тем более таинственным. В этой
статье я опишу обычный порядок перекомпиляции системы, ее ядра, а также
основные опции и параметры команды make, используемые в процессе компиляции для
систем, основанных на процессорах семейства Intel x86. На вашей машине должны
быть установлены инструменты разработки – gcc, make и все соответствующие
библиотеки и заголовочные файлы.
Исходные тексты операционной системы обычно
находятся в каталоге /usr/src. Для их обновления до текущей версии чаще всего
используется программа cvsup, устанавливаемая из коллекции пакетов FreeBSD.
cvsup является разновидностью CVS [2] (concurrent versions system, одна из широко
распространенных систем управления версиями программ, используемых для
групповой разработки программного обеспечения. СVS обеспечивает подмножество ее
функций, необходимое для синхронизации локальных файлов с файлами,
расположенными на master-сервере cvsup. При работе cvsup передает только
различия (diffs) между измененными со времени последнего обновления файлами, а
также может использовать компрессию потока (с использованием zlib), что
позволяет этому методу обновления существенно выигрывать в производительности и
нагрузке на канал по сравнению, например, c FTP.
Данная программа вызывается с
параметром, указывающим местоположение файла, описывающего следующие основные
параметры:
n местонахождение исходных текстов OS на
локальном винчестере;
n имя сервера, на котором расположен репозиторий
с исходными текстами, соответствующими текущей версии;
n части операционной системы (например, игры,
библиотеки, ядро или вся система целиком), подлежащие обновлению.
Рассмотрим подробно два параметра
– default tag и список коллекций для обновления. Параметр default tag
указывает, до какой ветки FreeBSD вы хотите производить апгрейд. Возможные
варианты:
n . (точка) – FreeBSD-current. FreeBSD «с
переднего края». Не рекомендуется тем, кто только осваивает процесс перекомпиляции.
n RELENG_5_0 – FreeBSD 5.0. Ветка 5.0-RELEASE,
используется для критических багфиксов и патчей системы безопасности.
n RELENG_4. Ветка FreeBSD-4.x. Сейчас это
FreeBSD-STABLE. Основная ветвь развития четвертой версии системы.
n RELENG_4_7. FreeBSD-4.7-RELEASE, используется
для критических багфиксов и патчей системы безопасности.
n RELENG_4_6. FreeBSD 4.6 и 4.6.2, используется
для критических багфиксов и патчей системы безопасности.
n RELENG_4_5. FreeBSD 4.5, используется для
критических багфиксов и патчей системы безопасности.
n RELENG_4_4. FreeBSD 4.4, используется для
критических багфиксов и патчей системы безопасности.
n RELENG_4_3. FreeBSD 4.3, используется для
критических багфиксов и патчей системы безопасности.
n RELENG_3. Ветка FreeBSD-3.x. Сейчас это
3.x-STABLE. Основная ветвь развития третьей версии системы.
n RELENG_2_2. Ветка FreeBSD-2.2.x. Устаревшая
ветвь.
Чем отличается RELEASE от STABLE? Очень просто:
STABLE – это то, что получается из RELEASE в процессе его (релиза) технического
сопровождения, то есть исправления ошибок и латания обнаруженных дыр в
безопасности. Отдельным пунктом здесь стоит версия системы, обозначаемая тегом
RELENG_4, которая представляет собой «стабильную ветвь разработки». Рано или
поздно на основе этой версии будет выпущена версия 4.8-RELEASE
(RELENG_4_8_0_RELEASE), от которой, в свою очередь, отойдет 4.8-STABLE
(RELENG_4_8).
Переходим к списку коллекций.
cvsup понимает следующие коллекции, относящиеся к исходным текстам операционной
системы:
n src-all – Полное дерево исходников.
n src-base – Базовые программы.
n src-bin – Программы в /usr/src/bin – то, что
после установки находится в /bin.
n src-contrib – Contributed software, в том
числе awk, gcc, tcpdump и многое другое, без чего не обойтись.
n src-etc – То, что с помощью mergemaster'а
устанавливается в /etc.
n src-games – Игры.
n src-gnu – GNU software.
n src-include – .h-файлы для помещения в
/usr/include.
n src-kerberos5 – Kerberos 5.
n src-kerberosIV – Kerberos 4.
n src-lib – Исходники системных библиотек.
n src-libexec – Некоторые демоны. Складываются в
/usr/libexec.
n src-release – Инструменты для построения
дистрибутива.
n src-sbin – Будущее содержимое /sbin.
n src-share – Будущее содержимое /usr/share.
n src-sys – Исходники ядра.
n src-tools – Инструменты для тестирования и
поддержки системы. Не собираются во время buildworld.
n src-usrbin – Будущее содержимое /usr/bin.
n src-usrsbin – Будущее содержимое /usr/sbin.
n src-crypto src-eBones src-secure src-sys-crypto
– Криптоподсистема.
Еще раз подчеркну, что коллекция src-all включает
в себя все остальные коллекции, так что если в sup-файле вы указали «src-all»,
нет надобности указывать еще какие-либо коллекции. С другой стороны, FreeBSD
Handbook [1] рекомендует не обновлять userspace программы отдельно от ядра и
наоборот, так как это может привести к неработоспособности программ из-за
несоответствий структур данных (простой пример – команда ps, часто не
работающая с ядром, версия которого не соответствует версии остальной системы).
Полностью формат sup-файла описан в документации
по cvsup. Далее в этой статье я предполагаю, что параметр default tag
установлен в значение «RELENG_4», соответствующий версии системы 4.x-STABLE, и
производится обновление системы целиком (используется тег src-all). При этом
наш sup-файл имеет примерно следующий вид:
--== cut /etc/cvsupfile.sys
==--
# Файл обновления системы
*default
host=cvsup5.FreeBSD.org
*default base=/usr
*default prefix=/usr
*default release=cvs
*default tag=RELENG_4
*default delete
use-rel-suffix compress
src-all
# src-base
# src-bin
# src-contrib
# src-etc
# src-games
# src-gnu
# src-include
# src-kerberos5
# src-kerberosIV
# src-lib
# src-libexec
# src-release
# src-sbin
# src-share
# src-sys
# src-tools
# src-usrbin
# src-usrsbin
# src-crypto
# src-eBones
# src-secure
# src-sys-crypto
--== end cut ==--
Запускаем cvsup:
--== cut here ==--
ice.root# cvsup
/etc/cvsupfile.sys
Connected to
cvsup5.FreeBSD.org
Updating collection
src-all/cvs
Edit src/etc/Makefile
[выводимые сообщения опущены]
Edit
src/share/misc/pci_vendors
Finished successfully
ice.root#
--== end cut ==--
После успешного завершения работы cvsup в
каталоге /usr/src нашего компьютера находятся исходные тексты, соответствующие
текущему содержанию CVS-репозитория ветки STABLE четвертого релиза FreeBSD.
Теперь переходим к компиляции.
Сначала просмотрим файл, настройки которого
влияют на конфигурацию и производительность получаемой в результате системы –
/etc/make.conf (или /etc/defaults/make.conf). В нем вы можете задать параметры
оптимизации для компилятора, указать, компилировать ли профилировочные версии
библиотек, sendmail, поставляемый с системой, perl, а также некоторые другие
опции. Интересное замечание насчет параметров оптимизации: FreeBSD Handbook [1]
рекомендует выставлять флаг оптимизации «-O», но ничто не мешает вам выставить,
к примеру «-O3 -march=i686», хотя, конечно, это скажется на времени компиляции.
Еще одно важное замечание: если вы производите апгрейд с версии FreeBSD
4.7-RELEASE или ниже на 4-STABLE, обязательно выставьте параметр 2COMPAT3X» файла
/etc/make.conf в значение «yes», иначе при запуске программ, скомпилированных
для FreeBSD 3.x (одной из таких программ является JDK 1.1.8, содержащийся в
ports), вы увидите сообщение динамического редактора связей о ненайденном
символе __stderrp в системных библиотеках.
Начнем с конфигурации ядра. Традиционно в
4.3BSD-based системах, к которым относится и FreeBSD, конфигурация ядра
описывается в текстовом файле, который затем с помощью команды config
преобразуется в h-файлы и Makefile, используемые непосредственно инструментами
компиляции. Примеры файлов конфигурации находятся в каталоге
/usr/src/sys/i386/conf и называются GENERIC и LINT. Для создания своей
конфигурации скопируйте файл GENERIC в файл, к примеру:
MYCONF:
cd /usr/src/sys/i386/conf
cp GENERIC MYCONF
и приступайте к его редактированию. Значения опций довольно
подробно описаны в файле LINT, и я не буду повторно описывать их здесь. Естественно,
вы должны отчетливо представлять себе аппаратную конфигурацию вашей машины. И
еще один совет: на первых порах случается всякое, поэтому лучше вносить
серьезные изменения в конфигурацию ядра той же версии, под которой в данный
момент работает ваш компьютер, то есть до обновления исходников через cvsup.
Такой подход имеет два преимущества:
n исключается полная перекомпиляция системы (то
есть make buildworld не выполняется – только make buildkernel, так как
установленная система той же версии, что и собираемое ядро), что значительно
уменьшает время итерации;
n больше возможности сохранить работоспособность
системы при загрузке со старым ядром в случае неработоспособности вновь
собранного из-за того же самого соответствия версии системы версии ядра.
После завершения редактирования перейдите в
каталог /usr/src и дайте команду сборки системы: cd /usr/src make buildworld.
Время выполнения этой команды зависит от заданных ранее опций компиляции и
может составить от часа до нескольких часов. Если вы компилируете на
многопроцессорной машине, имеет смысл выполнять make с ключом -j<n+2>,
где n – количество процессоров:
make -j4 buildworld
Внимание! Для сборки системы вам потребуется
около 300 Мб свободного места на разделе файловой системы, содержащем каталог
/usr/obj.
После окончания сборки системы остается только
скомпилировать ядро:
make buildkernel
KERNCONF=MYCONF
Здесь MYCONF – имя того самого файла конфигурации
ядра в каталоге /usr/src/sys/i386/conf, который вы недавно редактировали.
Обратите внимание, что команда make выполняется в каталоге /usr/src, а имя
файла конфигурации передается ей без пути до него. После успешного завершения работы
make перейдите в однопользовательский режим:
shutdown now
и, вновь войдя в каталог /usr/src cd /usr/src, выполните три заключительные
команды:
make installkernel
KERNCONF=MYCONF
make installworld
fastboot
При выполнении make installkernel ваше нынешнее
ядро будет скопировано в файл /kernel.old, а модули – в каталог /modules.old.
Это даст вам шанс все же запустить систему со старым ядром, если новое по
какой-либо причине окажется неработоспособным.
Совет: если вы компилировали ядро самый первый
раз (то есть то, которое перед выполнением make installkernel находится в файле
/kernel, заведомо работоспособно), перед make installkernel скопируйте его на
всякий случай, допустим, в /kernel.stable, чтобы оно не затерлось последующими
выполнениями make installkernel. У вас будет возможность впоследствии загрузить
его из командной строки начального загрузчика OS вместо ядра по умолчанию
/kernel. Описание работы с командами начального загрузчика выходит далеко за
рамки темы данной статьи, поэтому интересующихся мы отсылаем к страницам
онлайнового руководства по операционной системе, касающихся команд boot и
loader (man 8 boot и man 8 loader).
Если все прошло успешно, то после перезагрузки вы
будете работать в совершенно свежей операционной системе, только что собранной
практически своими руками. С другой стороны, нельзя не напомнить о
необходимости делать резервное копирование файловых систем перед началом
апгрейда.
Ссылки:
1. FreeBSD Handbook: http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/index.html
2. Concurrent versions system: http://www.cvshome.org