Илья Александров
Создаём собственную ОС на базе Linux
Дистрибутивов Linux существует сотни, и неизвестно, сколько появится еще. Десятки компаний и тысячи программистов соревнуются в создании лучшего Linux-проекта, а между тем любой опытный пользователь может стать автором системы для домашнего ПК, не уступающей продуктам гигантов IT-индустрии.
За долгие годы работы с Linux мною было использовано огромное количество различных дистрибутивов: Mandriva, Fedora, SlackWare, Debian, Ubuntu и многие другие. Какой-то проект нравился больше, какой-то – меньше. Но во всех дистрибутивах неминуемо приходилось сталкиваться с серьезными недостатками, которые сильно затрудняли работу. Один слишком требователен к ресурсам, в другом нет поддержки всего нужного оборудования, в третьем не хватает различного ПО. Вот тогда я вспомнил известную восточную мудрость: если нужно что-то сделать хорошо, сделай это сам.
Linux from Scratch
Я не единственный, кто решил заняться построением собственной версии Linux – ОС, в которой за основу будет взята базовая часть системы и ядро, но где не будет ни единого лишнего килобайта от разработчика, то есть от вас. Большое количество Linux-дистрибутивов, не соответствующих требованиям пользователей, подтолкнуло Герарда Бикменса (Gerard Beekmans) к созданию дистрибутива, который даст возможность каждому собрать систему, где будут только необходимые ему компоненты и функции.
Стремление талантливого программиста вылилось в проект Linux from Scratch (www.linuxfromscratch.org), сокращенно – LFS. Этот проект, позволяет сконструировать «с нуля», из исходных кодов, свою операционною систему на базе Linux. Компиляция LFS проходит на компьютере с уже установленной Linux-системой, впрочем, подойдет и «продвинутый» Live-CD, например, Knoppix [6].
При этом Linux-система, используемая для сборки, может быть любой – обязательно лишь наличие компилятора и системных библиотек. Linux From Scratch трудно назвать дистрибутивом в привычном смысле этого слова – это что-то вроде вспомогательного ПО, которое вкупе с базовой частью операционной системы позволит вам создать свою, уникальную версию ОС.
Как известно, Линус Торвальдс разрабатывал свою операционную систему под девизом «Just for fun!» – то есть только ради удовольствия. Нужно признать, что LFS действительно не часто можно встретить на серверах, используют эту систему, как правило, компьютерные энтузиасты. Установка и работа с Linux from Scratch поможет вам разобраться во взаимосвязи компонентов ОС, что пригодится при собственных разработках Linux-дистрибутива, причем не только на базе LFS. Поэтому LFS во многом рассчитан на тех людей, для которых процесс сборки собственного дистрибутива увлекателен и интересен – а таких людей, поверьте, немало.
Итак, если вы готовы потратить на конструирование системы целый день (а то и больше), то рекомендую скачать с сайта (2) LFS-packages-6.0, LFS-book, и продолжить читать эту статью.
Разбиение диска и создание дерева каталогов
Для лучшего понимания материала опишем весь ход процесса в общих чертах (см. рис. 1).
Рисунок 1. Схема сборки LFS
На первом этапе, с помощью уже инсталлированного дистрибутива или LiveCD, разбивается диск. На жестком диске выделяется раздел для новой системы. После чего на этом разделе нужно будет статически скомпилировать все необходимые программы и ядро системы. Далее происходит смена корневого каталога на раздел жесткого диска, отведенный под нашу новою ОС. Потребуется повторить компиляцию, но на этот раз ПО должно быть собрано динамически (отличие динамической компиляции от статической будет описано ниже). Последний этап включает в себя сборку важнейшей библиотеки glibc и конфигурацию установленной ОС. Как видите, ничего особенно сложного делать не придется.
На протяжении всего процесса ваш главный помощник – документация из пакета LFS-book, русский перевод которой можно взять тут: http://multilinux.sakh.com/download/lfsbook.tar.bz2. В книге подробно описан каждый шаг создания ОС, поэтому обязательно обращайтесь к этому руководству в случае возникновения проблем (данная статья не призвана заменить такую обширную документацию).
Создаем новый раздел – в моем случае это /dev/hda5, так как раздел /dev/hda1 уже занят установленным на жесткий диск Linux Slackware. Рекомендуется предварительно сделать бэкап системы, дабы можно было ее восстановить в случае повреждения, хотя вероятность подобного близка к нулю. И тут, думаю, все понятно: выделяем нужное количество (достаточно 23 Гб) под корневой каталог, пространство, равное удвоенному объему ОЗУ – под swap-раздел, по желанию можно создать отдельные разделы для домашнего каталога (/home) и для /boot. Впрочем, излюбленный многими вариант разбиения – отвести под корневой каталог все доступное пространство минус swap, и последующее создание собственно swap – также вполне допустимо при сборке LFS. На компьютере автора и Linux Slackware, являющийся родительской ОС, и LFS, используют один жесткий диск, впрочем, установить LFS на другой винчестер тоже труда не составит.
Файловую систему выбирайте на ваше усмотрение: и с Ext3, и с ReiserFS никаких проблем под LFS не было. А вот поклонников XFS придется огорчить – попытки заставить Linux From Scratch работать с этой ФС не увенчались успехом.
Теперь монтируем раздел, отведенный под новую ОС:
$ mount /dev/hda5 /mnt/mylin
Для удобства определим переменную MYLIN:
$ export MYLIN=/mnt/mylin
Отлично, для дальнейшей работы лучше создать отдельного пользователя mylin, которого и назначим владельцем смонтированного раздела.
$ useradd mylin
$ chown –R mylin $MYLIN
Нужно создать дерево каталогов в корне нового раздела:
$ cd $MYLIN
$ mkdir –p bin boot dev etc home lib mnt opt root sbin usr/{X11R6,local} var
В каталогах usr, usr/X11R6, usr/local создаем необходимую структуру: подкаталоги bin, etc, include, lib, sbin, share, src.
Затем то же самое проделаем для каталогов /var и /opt будущей системы:
$ mkdir var/{cache,lib,local,lock,log,opt,run,spool}
$ mkdir opt/{bin,doc,include,info,lib,man}
Не будем забывать, что существуют более глубокие иерархии, например, /usr/share/man/man1. Но объем статьи не позволяет привести здесь всю информацию о структуре файлового дерева, поэтому нужно либо воспользоваться документом Filesystem Hierarhy Standart (можно найти по адресу: http://linux-ve.net/MyLDP/file-sys/fhs-2.2-rus), либо внимательно изучить структуру уже установленной у вас ОС семейства Linux. После подготовки жесткого диска приступаем к статической сборке.
Статическая сборка
Зачем мы используем статическую сборку? При статической компиляции исходный код библиотеки присоединяется к коду приложения, что влечет за собой увеличение его размера, но при этом сохраняется целостность. При динамической же компиляции библиотека находится в отдельном файле, к которому по мере необходимости обращаются приложения. В итоге все программы работают с одной версией библиотеки
Но когда мы посредством команды chroot установим корневой каталог для вновь собираемой системы, библиотеки «родительской», установленной системы, находящиеся в /lib, /usr/lib, и прочих, станут уже недоступны, поэтому динамически скомпилированные программы работать откажутся, вдобавок совместимость версий никем не гарантирована.
Чтобы избежать этого, все необходимое программное обеспечение для нашей будущей системы мы для начала соберем статически. Начнем, пожалуй, с командного интерпретатора bash. (Поклонники ZSH или TCSH могут установить любимые интерпретаторы после установки системы, но на этапе сборки их использование не предусмотрено автором LFS). Следует проверить, есть ли у вас файл /usr/lib/libcurses.a и если его нет – установите пакет nсursesdev. Все пакеты надо собирать с флагами статической сборки: «--enable-static-link», «--disable-shared» или «--static». Какой именно подходит в каждом конкретном случае, можно узнать из документации к конкретному пакету или из вывода конфигурационного сценария, запущенного с параметром «--help».
$ ./configure –-help
Чтобы не спутать позже статически скомпилированные программы с «динамическими», создадим для них специальный каталог:
$ mkdir $MYLIN/stat
При сборке и установке пакетов не забываем добавлять параметр «--prefix=$MYLIN/stat» для перемещения файлов именно в этот каталог. И, наконец, ставим bash:
$ ./configure –-enable-static-link --prefix=$MYLIN/stat
$ make
$ make install
По такой же схеме собираем остальные необходимые пакеты: binutils, bzip2, textutils, texinfo, tar, sh-utils, gcc, grep, gzip, gawk, diffutils, fileutils, make, patch, sed, и, собственно, linux-kernel.
Да, при компиляции ядра не забываем, что для старых версий ядер (2.2.x-2.4.x) нужно использовать gcc 2.95, а для текущей версии 2.6.x рекомендуется применить gcc 3.x, дабы не возникло проблем.
Не забываем заглядывать в соответствующие разделы LFS-book, там сказано об этом и многих других нюансах. В целом же компиляция ядра в LFS не отличается от подобной процедуры, проводимой при использовании установленного на HDD дистрибутива. Разархивируем исходники ядра в $MYLIN/usr/src/linux-2.6.xx, после чего конфигурируем, запуская:
$ make menuconfig
Процесс настройки параметров ядра многократно описан в Интернете (6), вряд ли есть необходимость останавливаться на этом подробнее. Далее даем следующие команды в папке с исходными текстами Linux-kernel:
$ make bzImage
$ make modules
Все, по адресу $MYLIN/usr/src/linux-2.6.xx/arch/i386/boot/bzImage находится новое ядро.
Далее создаем файлы $MYLIN/etc/passwd и $MYLIN/etc/group. В первом прописываем пока единственного пользователя – root с любым паролем, а во втором группы пользователей (для начала одной группы root тоже будет достаточно).
На этом наши приготовления к следующему шагу закончились, и мы переходим уже к более тонкой динамической сборке.
Динамическая сборка
Теперь нам нужно сменить корневой каталог на /mnt/mylin, где мы будем пользоваться только статически собранными утилитами – к помощи инструментов из «родительской» ОС мы уже прибегать не сможем. Даем команду в консоли:
$ chroot $MYLIN/usr/bin/env –i
>HOME=/root TERM=$TERM PS1=’u:w$’
>PATH=/bin: /usr/bin: /sbin: /usr/sbin: /stat/sbin
>/stat/bin/bash --login
Этой командой мы указали пути к исполняемым файлам, тип терминала, интерпретатор и вид приглашения командной строки.
Для обеспечения работы некоторых программ, надо установить файловую систему proc в новой системе.
$ mount proc /proc -t proc
Наступил самый ответственный момент. Сборка библиотеки glibc. Самый ответственный он потому, что работать без нее большинство необходимых программ не будет, а в использовании Linux без основной библиотеки смысла нет. Сборка glibc же зачастую доставляет массу проблем.
При сборке мы указывали параметр «--prefix=$MYLIN/stat», поэтому при смене корня все статически собранные пакеты окажутся в каталоге /stat раздела новой ОС.
Итак, распаковываем архив glibc-2.x.x.tar.gz (например, в директорию /usr/src/) и переходим в каталог glibclinuxthreads. Придется немного подправить исходный код ввиду того, что на данном этапе в системе невозможна идентификация пользователя по имени (как раз из-за отсутствия glibc и других библиотек), и того, что для установки glibc нужен интерпретатор Perl, которого у нас нет.
Заменяем имя пользователя root в файле login/Makefile на его uid, то есть 0, а переменную $PERL в файле malloc/Makefile следует заменить на путь к интерпретатору – /usr/bin/perl – и при конфигурировании он просто будет проигнорирован.
Далее:
$ /usr/src/glibc-2.x.x/configure --prefix=/usr --enable-add-ons --libexecdir=/usr/bin &&
& make
& make install
$ make localedata/install-locales
$ /stat/bash --login
Если вы все сделали правильно, glibc скомпилируется, в строке приглашения наконец-то появится «root», и можно будет динамически перекомпилировать все программы.
Завершим установку ядра:
$ make modules_install
$ make install
Чтобы переместить новое ядро в каталог /boot, выполняем еще одну команду:
$ make unstall
Собираем все установленные и некоторые новые программы, теперь уже без флагов статической компиляции. Нам потребуются (на данном этапе очень важно не забыть скомпилировать все нижеперечисленное) (см. таблицу 1).
Таблица 1. Необходимый набор пакетов для сборки
autoconf
|
grep
|
perl
|
automake
|
groff
|
man
|
bash
|
gzip
|
procinfo
|
bin86
|
kbd
|
procps
|
binutils
|
less
|
psmisc
|
bzip2
|
|
reiserfs-progs
|
diffutils
|
libtool
|
sed
|
e2fsprogs
|
lilo
|
sh-utils
|
ed
|
m4
|
shadow
|
file
|
make
|
sysklogd
|
fileutils
|
makedev
|
sysvinit
|
findutils
|
man-pages
|
tar
|
flex
|
modutils
|
texinfo
|
gawk
|
ncurses
|
textutils
|
gcc
|
netkitbase
|
util-linux
|
bison
|
net-tools
|
vim
|
gettext
|
patch
|
|
После выполнения динамической перекомпиляции можно удалить каталог со статически собранными пакетами:
$ rm -rf /stat
Можно облегченно вздохнуть и выпить кофе – самое сложное, рутинное осталось позади. Переходим к следующему этапу – начальному конфигурированию нашей системы.
Начальное конфигурирование системы
Перед тем как приступить к настройке, замечу, что все изменения нужно делать в файлах каталога новой ОС, а не родительской системы.
Для установки системного времени создадим файл /etc/sysconfig/clock, содержащий всего одну строку:
UTC=0
Теперь часы компьютера будут отображать время вашего часового пояса – при условии, что значение времени в BIOS установлено верно.
Дадим компьютеру имя:
echo "HOSTNAME=my_linux" > /etc/sysconfig/network
Теперь разделы, которые система должна монтировать при загрузке, укажем в /etc/fstab:
# filesystem mount-point fs-type options dump fsck-order
/dev/hda5 / ext3 defaults 1 1
/dev/hda3 swap swap pri=1 0 0
proc /proc proc defaults 0 0
Вместо /dev/hda3 и /dev/hda5 напишите ваши разделы (корневой и swap), дополните файл при необходимости точками монтирования других разделов жесткого диска и CD-ROM.
Теперь сделаем нашу систему загружаемой.
Если помимо lFS вы пользуетесь другими дистрибутивами Linux, то сейчас нужно войти в старую систему – для этого выполняем команду:
$ exit
Уже в родительской ОС в файл /etc/lilo.conf добавляем следующее:
# LFS
image=/boot/bzImage
label=lfs
root=<partition>
read-only
Понятно, что «/boot/bzImage» – это путь к скомпилированному вами ядру системы, а «partition» – раздел диска, где находится корневой каталог.
Если же вы не планируете пользоваться другими операционными системами и дистрибутивами Linux, то сразу переходите к настройке LILO в LFS.
В этом случае lilo.conf будет выглядеть примерно так:
boot=/dev/hda
delay=40
compact
vga=normal
root=/dev/hda1
read-only
image=/boot/zImage-2.6.12
label=Linux
Сделайте необходимые изменения в зависимости от вашей конфигурации. Обновляем загрузчик командой:
$ /sbin/lilo –v
И, если все предыдущие этапы были выполнены правильно, мы окажемся в новой системе. Однако долгий этап «тонкой» настройки (отдельное внимание стоит уделить безопасности новой системы, ибо LFS по умолчанию выглядит довольно-таки незащищенным, как и всякая вновь установленная ОС) еще впереди. Зато собственноручно собранная версия Linux у вас уже есть.
Постскриптум
Герард Бикменс – не единственный, кому пришло в голову создать собственный Linux. Другой проект – BYOLinux, руководителем которого являлся Джонатан Торп (Jonatan Thorpe), на сегодняшний день свое развитие прекратил, хотя написанная имдокументация сохраняет актуальность и сейчас, но она не так детальна, как LFS-book и не переведена на русский. Главное отличие метода Джона в том, что библиотека glibc переносится из родительской системы в дочернюю без перекомпиляции, это не столь эффективно, но позволяет избежать многих проблем при сборке. Желание почувствовать себя конструктором ОС испытывают и некоторые пользователи FreeBSD.
Теперь такое вполне возможно – по адресу http://ezine.daemonnews.org/200302/fbsdscratch.html находится статья о сборке FreeBSD из исходников целиком – от distributions до портов, причем методом не похожим на обычный «rebuild» системы, но схожим с методом Герарда Бикменса. Что ж, теперь и у вас есть личная, уникальная система, созданная на базе Linux. В случае возникновения проблем ищите их решение в LFS-book, там все подробно описано. Также рекомендую с портала http://www.tldp.org скачать руководство Linux Network Administrator’s Guide, оно хоть и не относится непосредственно к LFS, но пригодится на этапе настройки системы. Не стоит забывать, что с каждой программой поставляются также различные man и info pages, также призванные облегчить жизнь линуксоида.
Литература и ссылки
- LFS-book на русском – http://multilinux.sakh.com/lfs.
- Официальный портал проекта LFS – http://www.linuxfromscratch.org.
- Портал ByoLinux – http://www.byolinux.org.
- Cтатья о FreeBSD from scratch – http://ezine.daemonnews.org/200302/fbsdscratch.html.
- Статья о компиляции ядра Linux – http://vikos.lrn.ru/MyLDP/kernel/kompil-2-6.html.
- Байрак А. Обзор Knoppix 3.7 Russian Edition. – Журнал «Системный администратор», №3, март 2005 г. – 4-6 с. (http://www.samag.ru/cgi-bin/go.pl?q=articles;n=03.2005;a=02).
Ссылки на все указанные в статье программы приведены в LFS-book (Часть 3. Приложения).