Журнал LinuxFormat - перейти на главную

LXF170:Дис­тро­ст­рой: сде­ла­ем са­ми

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Новая страница: «Категория: Учебники == Со­би­ра­ем ди­ст­ри­бу­тив Linux == ''Воо­ру­жась под­го­тов­лен­…»)

Версия 07:12, 17 ноября 2018

Содержание

Со­би­ра­ем ди­ст­ри­бу­тив Linux

Воо­ру­жась под­го­тов­лен­ны­ми ин­ст­ру­мен­та­ми, Дмит­рий Куз­не­цов за­вер­ша­ет де­ло по­строе­ния ми­ни­маль­но­го ди­ст­ри­бу­ти­ва Linux.

(thumbnail)
Наш эксперт Дмит­рий Куз­не­цов бо­лее 10 лет ве­дет не­рав­ный бой с мон­ст­ра­ми слож­но­сти, хо­тя не­ко­то­рые по­че­му-то их счи­та­ют вет­ря­ны­ми мель­ни­ца­ми.

На про­шлом уро­ке мы об­за­ве­лись ин­ст­ру­мен­та­ри­ем для сбор­ки ди­ст­ри­бу­ти­ва. Те­перь на­ста­ло вре­мя при­менить его на де­ле!

Сбор­ка ком­понен­тов

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

1 По­лу­чение ис­ход­ных ко­дов (на­при­мер, за­груз­ка ар­хи­ва).

2 Под­го­тов­ка ис­ход­ных ко­дов (на­при­мер, их рас­па­ков­ка в ра­бо­чий ка­та­лог).

3 Кон­фи­гу­ри­ро­вание (на­при­мер, за­пуск ./configure с нуж­ны­ми па­ра­мет­ра­ми).

4 Ком­пи­ля­ция (на­при­мер, за­пуск make).

5 Ус­та­нов­ка (на­при­мер, за­пуск make install).

Де­таль­ные ин­ст­рук­ции по сбор­ке кон­крет­но­го про­ек­та вы уз­наете толь­ко из его до­ку­мен­та­ции. Это един­ст­вен­но вер­ный путь!

За­груз­чик Grub

Са­мый из­вест­ный и раз­ви­тый за­груз­чи­к для ПК –Grub. Он ис­поль­зу­ет­ся боль­шин­ст­вом со­ве­мен­ных ди­ст­ри­бу­ти­вов Linux, в том чис­ле и Ubuntu. Соберем его, действуя по нашей схеме.

1 Ис­ход­ные ко­ды Grub мож­но за­гру­зить с сай­та gnu.org в ви­де ар­хи­ва в фор­ма­те tar.xz: wget -nd -P /root/work/download/ ftp://ftp.gnu.org/gnu/grub/grub-1.99.tar.xz.

2 В дан­ном слу­чае тре­бу­ет­ся толь­ко рас­па­ко­вать ар­хив в ра­бо­чий ка­та­лог:

tar -C /root/work/src -xvf /root/work/download/grub-1.99.tar.xz

cd /root/work/src/grub-1.99/

3 Скон­фи­гу­ри­ро­вать Grub про­сто: за­дайте нуж­ный ком­пи­ля­тор C в пе­ре­мен­ной ок­ру­жения CC и за­пустите скрипт configure с па­ра­мет­ром prefix, ука­зывающим ка­та­лог для уста­нов­ки (обыч­но /usr).

На беду, у ключа prefix в Grub двой­ное на­зна­чение: во-первых, он указывает ме­сто уста­нов­ки (ка­та­лог, ку­да скла­ды­вать ре­зуль­та­ты сбор­ки по ко­ман­де make install); а во-вторых, ком­понен­ты Grub ищут друг дру­га по это­му пу­ти, ра­бо­тая в со­ста­ве ди­ст­ри­бу­ти­ва. Итак, по­лу­ча­ется два ва­ри­ан­та сбор­ки. Пер­вый ва­ри­ант:

» При сбор­ке ука­зы­ва­ем prefix=/root/work/src/_install_grub. Make install скла­ды­ва­ет ре­зуль­та­ты сбор­ки в /root/work/src/_install_grub (в /usr ниче­го не за­ти­ра­ет­ся). Но в фай­ло­вой сис­те­ме ди­ст­ри­бу­ти­ва мы вы­ну­ж­де­ны раз­мес­тить Grub то­же в /root/work/src/_install_grub (ина­че ком­понен­ты не смо­гут най­ти друг дру­га).

Ва­ри­ант дол­жен ра­бо­тать, но очень хо­чет­ся раз­мес­тить за­груз­чик в /usr. Вто­рой ва­ри­ант:

» При сбор­ке ука­зы­ва­ем prefix=/usr. Make install скла­ды­ва­ет ре­зуль­та­ты сбор­ки в /usr, за­ти­рая сис­тем­ный Grub.

Тут уж со­всем все пло­хо. По­это­му пред­ла­га­ет­ся путь, со­вме­щаю­щий досто­ин­ст­ва обо­их ва­ри­ан­тов:

» Бе­рем два де­ре­ва ис­ход­ных ко­дов Grub.

» В пер­вом де­ре­ве со­би­ра­ем Grub с prefix=/usr (толь­ко make install не де­ла­ем), во вто­ром де­ре­ве со­би­ра­ем Grub с prefix=/root/work/src/_install_grub (make install то­же не де­ла­ем).

» В пер­вом де­ре­ве за­ме­ня­ем все Makefile’ы на со­от­вет­ст­вую­щие из вто­ро­го де­ре­ва и вы­зы­ва­ем make install.

По­лу­ча­ем: make install скла­ды­ва­ет ре­зуль­та­ты сбор­ки в /root/work/src/_install_grub, но в фай­ло­вой сис­те­ме ди­ст­ри­бу­ти­ва мы мо­жем раз­мес­тить за­груз­чик в /usr.

Кон­фи­гу­ри­ро­вание с клю­чом prefix=/usr:

CC=/root/work/files/toolchain/result/bin/x86_64-unknown-linux-gnu-cc ./configure --prefix=/usr

4 Командуем CC=/root/work/files/toolchain/result/bin/x86_64-unknown-linux-gnu-cc make.

5 Итак, до це­ли – один шаг. Ос­та­лась од­на про­бле­ма, об­ход­ной путь для ре­шения ко­то­рой был обе­щан в раз­де­ле «На­строй­ка». Как уста­но­вить Grub, скон­фи­гу­ри­ровн­ный с клю­чом prefix=/usr, в ка­та­лог /root/work/src/_install_grub? Обыч­ная ко­ман­да make install уста­но­вит его в /usr и за­трет фай­лы сис­тем­но­го за­груз­чи­ка.

Порас­су­ж­даем ло­ги­че­­ски. Суть уста­нов­ки в про­стом ко­пи­ро­вании фай­лов в нуж­ный ка­та­лог. Вся ло­ги­ка это­го со­сре­до­то­че­на в Makefile’ах. Значит, нуж­но их от­кор­рек­ти­ро­вать должным об­ра­зом. Но при кон­фи­гу­ри­ро­вании с клю­чом prefix=/root/work/src/_install_grub нуж­ные Makefile’ы соз­да­ют­ся ав­то­ма­ти­че­­ски. Ис­поль­зо­вание их при уста­нов­ке ре­ша­ет по­став­лен­ную за­да­чу.

Соз­да­дим Makefile’ы для уста­новки Grub в локаль­ный ка­та­лог:

mkdir /root/work/src/grub-1.99_temp/

tar -C /root/work/src/grub-1.99_temp/ -xvf /root/work/download/grub-1.99.tar.xz

cd /root/work/src/grub-1.99_temp/grub-1.99/

CC=/root/work/files/toolchain/result/bin/x86_64-unknown-linux-gnu-cc ./configure –prefix=/root/work/src/_install_grub

За­меним Makefile’ы (их всего шесть) в основ­ном де­ре­ве ис­ход­ных ко­дов. Мож­но ко­пи­ро­вать по од­но­му вруч­ную, но удобнее сделать это из ко­ман­дной строки:

cd /root/work/src/grub-1.99_temp

find ./grub-1.99/ | grep «Makefile$» | xargs -I {} -t cp --remove-destination {} .{}

На­ко­нец-то мож­но ус­та­но­вить Grub в ло­каль­ный ка­та­лог:

cd /root/work/src/grub-1.99/

make install

Действительно, в ка­та­ло­ге /root/work/src/_install_grub лежит го­то­вый за­груз­чик.

Описанный трюк с за­ме­ной Makefile’ов не стоит считать универ­саль­ным прие­мом. Нет никаких гарантий, что он сра­бо­тает для дру­го­го ПО или да­же дру­гих вер­сий Grub.

Яд­ро Linux

1 Ис­ход­ные ко­ды яд­ра уже за­гру­же­ны, о чем за нас по­за­бо­тил­ся crosstool-ng. Ар­хив в фор­ма­те tar.xz ле­жит здесь: /root/work/download/linux-3.2.25.tar.xz.

2 Нуж­но рас­па­ко­вать ар­хив в ра­бо­чий ка­та­лог:

tar -C /root/work/src/ -xvf /root/work/download/linux-3.2.25.tar.xz

cd /root/work/src/linux-3.2.25/

3 Во-пер­вых, в фай­ле Makefile корнево­го ка­та­ло­га ис­ход­ных ко­дов нуж­но уста­но­вить зна­чения пе­ре­мен­ных ARCH и CROSS_COMPILE (стро­ки 195 и 196) сле­дую­щим об­ра­зом:

ARCH ?= x86_64

CROSS_COMPILE ?= /root/work/files/toolchain/result/bin/x86_64-unknown-linux-gnu-.

Пер­вая оп­ре­де­ля­ет це­ле­вую ар­хи­тек­ту­ру со­би­рае­мо­го яд­ра. Вто­рая на­страи­ва­ет сис­те­му сбор­ки на применение нуж­но­го ин­ст­ру­мен­та­рия, пу­тем до­бав­ления ее зна­чения как пре­фик­са при вы­зо­ве ин­ст­ру­мен­тов сбор­ки. На­при­мер, в дан­ном слу­чае имя ком­пи­ля­то­ра из cc пре­вра­тит­ся в /root/work/files/toolchain/result/bin/x86_64-unknown-linux-gnu-cc. От­ре­дак­ти­ро­вать Makefile мож­но вруч­ную в лю­бом тек­сто­вом ре­дак­то­ре или с по­мо­щью команд:

sed -i 's/^ARCH.*?=.*$/ARCH ?= x86_64/' ./Makefile

sed -i 's/^CROSS_COMPILE.*?=.*$/CROSS_COMPILE ?= \/root\/work\/files\/toolchain\/result\/bin\/x86_64-unknown-linux-gnu-/' ./Makefile

Во-вто­рых, нуж­но соз­дать файл .config, с по­мо­щью ко­то­ро­го за­да­ет­ся кон­фи­гу­ра­ция яд­ра Linux. К сча­стью, в ис­ход­ных ко­дах для ка­ж­дой из под­дер­жи­вае­мых ар­хи­тек­тур есть при­ме­ры кон­фи­гу­ра­ций. Как и в слу­чае с crosstool-ng, удоб­но взять один из них за осно­ву, а за­тем немно­го под­кор­рек­ти­ро­вать в слу­чае необ­хо­ди­мо­сти. Но здесь не при­дет­ся ис­кать нуж­ный файл настройки в де­ре­ве ис­ход­ных ко­дов и ко­пи­ро­вать его вруч­ную. Для это­го есть спе­ци­аль­ная ко­ман­да make defconfig.

Она соз­даст файл .config в те­ку­щем ка­та­ло­ге на осно­ве стан­дарт­ной кон­фи­гу­ра­ции для дан­ной ар­хи­тек­ту­ры, ко­то­рая уже бы­ла за­да­на ранее в пе­ре­мен­ной ARCH.

Для из­менения кон­фи­гу­ра­ции яд­ра Linux слу­жит спе­ци­аль­ная ин­те­рак­тив­ная сис­те­ма, по­хо­жая на ту, что ис­поль­зу­ет­ся в crosstool-ng. За­пустить ее мож­но командой make menuconfig.

Пра­вок все­го три.

» В раз­де­ле Processor type and features вклю­чи­те Build-in kernel command line, а за­тем в Build-in kernel command string вве­ди­те root=/dev/sda1 rootfstype=ext4. Эта стро­ка опи­сы­ва­ет па­ра­мет­ры, ко­то­рые яд­ро бу­дет ис­поль­зо­вать при за­груз­ке. Здесь доста­точ­но ука­зать рас­по­ло­жение и тип корневой фай­ло­вой сис­те­мы.

» Как вид­но из пре­ды­ду­ще­го пунк­та, ис­поль­зу­ет­ся фай­ло­вая сис­те­ма ext4, по­это­му ее нуж­но вклю­чить: раз­дел File systems, па­ра­метр The Extended 4 (ext4) filesystem.

» В раз­де­ле Kernel hacking от­клю­чи­те Stack utilization instrumentation. Это из­ба­вит от на­зой­ли­вых со­об­щений о со­стоянии сте­ка. Они бывают по­лез­ны при от­лад­ке, но иначе толь­ко раз­дра­жа­ют.

Ос­та­лось за­крыть сис­те­му кон­фи­гу­ри­ро­вания (два­ж­ды на­жать Esc), со­гла­сив­шись с со­хранением из­менений в фай­ле .config. Кон­фи­гу­ра­ция яд­ра го­то­ва.

4 Ком­пи­лируем: make.

5 Го­то­вый об­раз яд­ра Linux п­ре­дстав­ля­ет со­бой един­ст­вен­ный файл /arch/x86/boot/bzImage, по­это­му уста­нов­ка не тре­бу­ет­ся.

При­клад­ное ПО и init

При­клад­ных про­грамм ве­ли­кое мно­же­ст­во. Да­же ес­ли ог­раничить­ся лишь основ­ны­ми ути­ли­та­ми команд­ной стро­ки, тра­ди­ци­он­ны­ми для лю­бо­го ди­ст­ри­бу­ти­ва Linux, опи­сание их сбор­ки за­ня­ло бы не один де­ся­ток страниц. К сча­стью, есть пре­крас­ный про­ект busybox. Он реа­ли­зу­ет функ­цио­наль­ность init, shell и еще бо­лее чем 300 про­грамм команд­ной стро­ки Linux. Да­же уди­ви­тель­но, что все это уме­ща­ет­ся в единствен­ном ис­пол­няе­мом фай­ле объемом 2,5 МБ. Не­ко­то­рые про­грам­мы слегка уре­за­ны – например, мо­жет от­сут­ст­во­вать под­держ­ка некоторых па­ра­мет­ров. Но на­до быть уж очень боль­шим фа­на­том кон­со­ли, что­бы ощу­щать эти неудоб­ст­ва. Оче­вид­но, что в дан­ном слу­чае вполне ра­зум­но ис­поль­зо­вать busybox. Не­об­хо­ди­мо толь­ко сде­лать два за­ме­чания:

» Син­так­сис фай­ла inittab, необ­хо­ди­мо­го для init, в busybox немно­го от­ли­ча­ет­ся от его клас­си­че­­ско­­го ана­ло­га.

» Ути­ли­та grep из busybox не уст­раи­ва­ет один из ск­риптов в Grub. Ис­сле­до­вания по­ка­за­ли, что все де­ло в па­ра­мет­ре -x. По­это­му grep при­дет­ся со­брать от­дель­но. Воз­мож­но, в бу­ду­щих вер­си­ях busybox эта про­бле­ма бу­дет ис­прав­ле­на.

1 Ис­ход­ные ко­ды busybox мож­но за­гру­зить с сай­та про­ек­та в ви­де ар­хи­ва в фор­ма­те tar.bz2: wget -nd -P /root/work/download/ www.busybox.net/downloads/busybox-1.20.2.tar.bz2.

2 Рас­па­ков­ка ар­хи­ва в ра­бо­чий ка­та­лог:

tar -C /root/work/src/ -xjvf /root/work/download/busybox-1.20.2.tar.bz2

cd /root/work/src/busybox-1.20.2/

На сай­те про­ек­та для ка­ж­дой вер­сии busybox мож­но най­ти пат­чи (на мо­мент на­пи­сания ста­тьи для вер­сии 1.20.2 был досту­пен толь­ко один), ко­то­рые же­ла­тель­но за­гру­зить и при­менить к рас­па­ко­ван­ным ис­ход­ным ко­дам:

wget -nd -P /root/work/download/ www.busybox.net/downloads/fixes-1.20.2/busybox-1.20.2-kernel_ver.patch

patch -p1 </root/work/download/busybox-1.20.2-kernel_ver.patch

3 Кон­фи­гу­ри­ро­вание busybox и яд­ра Linux ана­ло­гич­ны: взять стан­дарт­ную кон­фи­гу­ра­цию, от­крыть ин­те­рак­тив­ную сис­те­му кон­фи­гу­ри­ро­вания и из­менить несколь­ко па­ра­мет­ров:

make defconfig

make menuconfig

Как всегда, пра­вок немно­го.

» В раз­де­ле Busybox Settings > Build Options уста­но­вить па­ра­метр Building BusyBox as a static binary (no shared libs). Он оз­на­ча­ет, что busybox нуж­но со­брать в ви­де един­ст­вен­но­го ис­пол­няе­мо­го фай­ла. Все под­дер­жи­вае­мые про­грам­мы бу­дут реа­ли­зо­ва­ны в ви­де сим­во­ли­че­­ских ссы­лок на него.

» Там же, па­ра­мет­ру Cross Compiler prefix уста­но­вить зна­чение /root/work/files/toolchain/result/bin/x86_64-unknown-linux-gnu-. Его смысл ана­ло­ги­чен пе­ре­мен­ной CROSS_COMPILE в яд­ре Linux.

» В раз­де­ле Network utilities > inetd от­клю­чить Support RPC services. Для сбор­ки с этим па­ра­мет­ром в ис­поль­зуе­мом ин­ст­ру­мен­та­рии не хва­та­ет за­го­ло­воч­ных фай­лов. По­сколь­ку эта воз­мож­ность не нуж­на, про­ще ее от­клю­чить, чем мо­дернизи­ро­вать ин­ст­ру­мен­та­рий.

Как и в слу­чае кон­фи­гу­ри­ро­вания яд­ра Linux, вый­дя из ин­те­рак­тив­ной сис­те­мы и со­гла­сив­шись с со­хранением из­менений в .config, по­лу­ча­ем го­то­вую кон­фи­гу­ра­цию busybox.

4 Ком­пи­ля­ция: make.

5 Ус­та­нов­ка: make install.

В од­ном из па­ра­мет­ров настройки мес­том уста­нов­ки был ука­зан ка­та­лог ./_install. Дей­ст­ви­тель­но, был соз­дан /root/work/src/busybox-1.20.2/_install с го­то­вым busybox.

Ос­та­лось со­брать grep. К сча­стью, это на­столь­ко про­сто, что не по­тре­бу­ет ника­ких по­яснений. Все бы про­грам­мы так со­би­ра­лись!

1 По­лу­чае­м ис­ход­ные ко­ды:

wget -nd -P /root/work/download/ ftp://ftp.gnu.org/gnu/grep/grep-2.10.tar.xz

2 Готовим ис­ход­ные ко­ды:

tar -C /root/work/src/ -xvf /root/work/download/grep-2.10.tar.xz

cd /root/work/src/grep-2.10/

3 Конфигурируем:

CC=/root/work/files/toolchain/result/bin/x86_64-unknown-linux-gnu-cc ./configure --prefix=/root/work/src/_install_grep

4 Компилируем:

CC=/root/work/files/toolchain/result/bin/x86_64-unknown-linux-gnu-cc make

5 Ус­та­нав­ливаем: make install.

Ус­та­нов­ка вы­пол­не­на в ка­та­лог /root/work/src/_install_grep.

За­го­тов­ка корневой ФС из crosstool-ng

Как уже го­во­ри­лось ранее, в Linux всем при­клад­ным про­грам­мам необ­хо­ди­ма стан­дарт­ная биб­лио­те­ка язы­ка C. Без нее не об­хо­дит­ся ни один ди­ст­ри­бу­тив. К сча­стью, она вхо­дит в со­став на­ше­го ин­ст­ру­мен­та­рия, по­это­му с ее сбор­кой во­зить­ся не при­дет­ся, об этом уже по­за­бо­тил­ся crosstool-ng. Со­б­ран­ную для це­ле­вой плат­фор­мы вер­сию мож­но най­ти здесь: /root/work/files/toolchain/result/x86_64-unknown-linux-gnu/sysroot/. Как нетрудно до­га­дать­ся по на­званию, со­дер­жи­мое ка­та­ло­га sysroot слу­жит от­лич­ной за­го­тов­кой для корневой фай­ло­вой сис­те­мы но­вого ди­ст­ри­бу­ти­ва.

Минималь­ный на­бор стар­то­вых скриптов

Ка­та­лог /etc лю­бо­го со­вре­мен­но­го ди­ст­ри­бу­ти­ва Linux со­дер­жит море сложней­ших ск­риптов и фай­лов настройки. С виду ка­жет­ся, что ра­зо­брать­ся в них невоз­мож­но. Но сто­ит по­гру­зить­ся в изу­чение, как ста­нет яс­но, что боль­шин­ст­во из них от­ве­ча­ют за на­строй­ки некой при­клад­ной про­грам­мы. Нет про­грам­мы, нет и со­от­вет­ст­вую­щих фай­лов. Для минималь­но­го ди­ст­ри­бу­ти­ва, опи­сы­вае­мо­го в дан­ной ста­тье, хватит трех. И их со­дер­жи­мое так при­ми­тив­но, что по­яснения мо­гут по­ка­зать­ся из­лишними.

Создание рабочего каталога:

mkdir /root/work/files/etc_files

cd /root/work/files/etc_files

Са­ми фай­лы мож­но соз­дать в лю­бом тек­сто­вом ре­дак­то­ре или, как по­ка­за­но ни­же, с по­мо­щью ко­манд echo.

» Файл /etc/inittab, ко­то­рый кон­фи­гу­ри­ру­ет init.

echo '::sysinit:/etc/rcS' >> ./inittab

echo 'tty1::respawn:/bin/sh' >> ./inittab

echo 'tty2::respawn:/bin/sh' >> ./inittab

echo 'tty3::respawn:/bin/sh' >> ./inittab

echo '::restart:/sbin/init' >> ./inittab

echo '::ctrlaltdel:/sbin/reboot' >> ./inittab

Смысл понятен, де­та­ли син­так­си­са прояснит до­ку­мен­та­ция.

» Файл /etc/rcS, ука­занный с inittab как стар­то­вый ск­рипт.

echo '#!/bin/sh' >> ./rcS

echo 'mount -av' >> ./rcS

echo 'mdev -s' >> ./rcS

echo 'echo «Hello, my micro linux!»' >> ./rcS

Этот обыч­ный ск­рипт команд­ной обо­лоч­ки вы­пол­ня­ет три дей­ст­вия:

> Мон­ти­ру­ет фай­ло­вые сис­те­мы, ука­зан­ные в фай­ле /etc/fstab.

> Соз­да­ет в ка­та­ло­ге /dev все необ­хо­ди­мые фай­лы уст­ройств. Здесь это де­ла­ет­ся с по­мо­щью про­грам­мы mdev из busybox, хо­тя в боль­ших ди­ст­ри­бу­ти­вах Linux обыч­но ис­поль­зу­ет­ся спе­ци­аль­ная сис­те­ма udev, ко­то­рая тре­бу­ет от­дель­ной сбор­ки и на­строй­ки.

> Вы­во­дит при­вет­ст­вие.

По­сколь­ку он бу­дет за­пускать­ся, дадим ему на это пра­ва:

chmod 777 ./rcS

» Файл fstab. Стро­го го­во­ря, он не обя­за­те­лен. Но труд­но удер­жать­ся от со­блаз­на все­го дву­мя строчка­ми по­лу­чить доступ к со­дер­жи­мо­му фай­ло­вых сис­тем proc и sysfs, ко­то­рые да­ют ог­ром­ное ко­ли­че­­ст­во по­лез­ной ин­фор­ма­ции о ра­бо­таю­щий сис­те­ме.

echo -e 'proc\t/proc\tproc\tdefaults\t0\t0' >> ./fstab

echo -e 'sysfs\t/sys\tsysfs\tdefaults\t0\t0' >> ./fstab

Все вме­сте

Итак, необ­хо­ди­мые ком­понен­ты го­то­вы. Ос­та­лось со­брать из них корневую фай­ло­вую сис­те­му бу­ду­ще­го ди­ст­ри­бу­ти­ва. Это дела­ет­ся про­стым ко­пи­ро­ванием по­лу­чен­ных ком­понен­тов в один ка­та­лог. Пер­вым де­лом нуж­но ско­пи­ро­вать за­го­тов­ку корневой фай­ло­вой сис­те­мы, соз­дан­ную crosstool-ng, в ра­бо­чий ка­та­лог:

cp -r /root/work/files/toolchain/result/x86_64-unknown-linux-gnu/sysroot/ /root/work/files/

Те­перь ту­да мож­но до­ба­вить все ос­таль­ные ком­по­нен­ты.

» Busybox

cp -r /root/work/src/busybox-1.20.2/_install/* /root/work/files/sysroot/

» Grep (про­грам­мы из па­ке­та grep долж­ны за­менить со­от­вет­ст­вую­щие сим­во­ли­че­­ские ссыл­ки busybox, по­это­му при ко­пи­ро­вании нуж­но ука­зать ключ remove-destination):

cp -r --remove-destination /root/work/src/_install_grep/* /root/work/files/sysroot/

» За­груз­чик Grub нуж­но ко­пи­ро­вать в ка­та­лог /usr, как бы­ло ука­за­но при сбор­ке:

cp -r /root/work/src/_install_grub/* /root/work/files/sysroot/usr/

» Стартовые скрипты и конфигурационные файлы

cp -r /root/work/files/etc_files/* /root/work/files/sysroot/etc

» Об­раз яд­ра Обыч­но рас­по­ла­га­ет­ся в ка­та­ло­ге /boot. Нуж­но соз­дать его и ско­пи­ро­вать ту­да bzImage, пе­ре­име­но­вав в со­от­вет­ст­вии с тре­бо­ва­ния­ми Grub в vmlinuz-3.2.25:

mkdir /root/work/files/sysroot/boot

cp /root/work/src/linux-3.2.25/arch/x86/boot/bzImage /root/work/files/sysroot/boot/vmlinuz-3.2.25

Ос­та­лось соз­дать пус­тые ка­та­ло­ги /proc, /sys и /dev для мон­ти­ро­ва­ния фай­ло­вых сис­тем и соз­да­ния фай­лов уст­ройств:

cd /root/work/files/sysroot/

mkdir proc sys dev

Корневая файловая система готова.

Запуск го­то­во­го ди­ст­ри­бу­ти­ва

Итак, можно считать, что дистрибутив Linux собран. На­до бы проверить его работоспособность и настроить загрузчик. Для этого нужено компьютер или раздел на жестком диске. Но свободный компьютер для экспериментов мало у кого найдется, а чтобы уверенно выполнять такие трюки на отдельном разделе жесткого диска своей рабочей машины, нужен немалый опыт. Идеальное решение – виртуальная машина (ВМ): делаешь все что угодно, а если что-то не вышло, всегда можно удалить файл с образом жесткого диска и попробовать еще раз. Ос­та­лось вы­брать эту ВМ.

Вир­ту­аль­ная ма­ши­на KVM

Тех­но­ло­гии вир­туа­ли­за­ции в по­следние го­ды до­воль­но бур­но раз­ви­ва­ют­ся, по­это­му вы­би­рать есть из че­го. Но вир­туа­ли­за­ция не яв­ля­ет­ся те­мой дан­ной ста­тьи, по­это­му хо­те­лось бы най­ти ре­шение по­про­ще. Тут внимание сра­зу при­вле­ка­ет KVM (Kernel Virtual Machine), ВМ яд­ра Linux. Она в яд­ре, а яд­ро уже есть; зна­чит, с ней будет мень­ше все­го про­блем. Здесь сле­ду­ет от­ме­тить, что по­пасть в яд­ро дав­но меч­та­ли все. Мно­гие го­ды шла из­ну­ри­тель­ная борь­ба за это «ме­сто под солн­цем». Но поя­ви­лась KVM – и в два сче­та обош­ла ста­рич­ков. По­бе­да, ви­ди­мо, бы­ла одер­жа­на ком­пакт­но­стью: для ра­бо­ты KVM доста­точ­но за­гру­зить один мо­дуль яд­ра и уста­но­вить QEMU для вир­туа­ли­за­ции вво­да/вы­во­да. Правда, такое ре­шение ра­бо­та­ет толь­ко на со­вре­мен­ных про­цес­со­рах Intel и AMD с ап­па­рат­ной реа­ли­зацией тех­но­ло­гии под­держ­ки вир­туа­ли­за­ции. Но эта про­бле­ма с ка­ж­дым го­дом те­ряет свое зна­чение. Про­ве­рить на­ли­чие у про­цес­со­ра данной функ­цио­наль­но­сти мож­но так (ес­ли вы­во­дит­ся ok, то под­дер­жи­ва­ет):

[ «`egrep '^flags.*(vmx|svm)' /proc/cpuinfo`» != “” ] && echo “ok”

Установить KVM просто:

apt-get install kvm qemu

Теперь загрузите нужный драйвер, и можно приступать к работе. Для процессоров AMD скомандуем modprobe kvm-amd, для процессоров Intel – modprobe kvm-intel. Ес­ли при за­груз­ке драй­ве­ра вы­да­ет­ся ошиб­ка Operation is not supported [Опе­ра­ция не под­дер­жи­ва­ет­ся], ве­ро­ят­но, в BIOS от­клю­че­на вир­туа­ли­за­ция.

Установка ОС

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

Пер­вым де­лом ну­жен сам же­ст­кий диск, на ко­то­рый бу­дет уста­нав­ли­вать­ся ОС. Для ВМ его роль иг­ра­ет обыч­ный файл, на­зы­ва­емый об­ра­зом же­ст­ко­го дис­ка. Для ра­бо­ты с ними в QEMU есть спе­ци­аль­ная про­грам­ма. Вот как с ее по­мо­щью мож­но соз­дать об­раз же­ст­ко­го дис­ка раз­ме­ром 1 ГБ:

qemu-img create /root/work/files/sysroot.img 1G

Это об­раз са­мо­го про­сто­го ти­па (raw-фор­мат), то есть обыч­ный файл, за­полнен­ный ну­ля­ми. С та­ким же успе­хом для его соз­дания мож­но бы­ло бы восполь­зо­вать­ся ко­ман­дой dd.

Итак, диск есть. Как с ним ра­бо­тать? С ре­аль­ны­ми же­ст­ки­ми дис­ка­ми все бы­ло бы по­нят­но: в Linux они пред­став­ле­ны фай­ла­ми в ка­та­ло­ге /dev. А с об­раз­ами? Хо­ро­шо бы уметь и с ними ра­бо­тать ана­ло­гич­но. Это воз­мож­но с по­мо­щью тех­но­ло­гии се­те­во­го блоч­но­го уст­рой­ст­ва (Network Block Device, NBD). Она да­ет воз­мож­ность ра­бо­тать с уда­лен­ны­ми же­ст­ки­ми дис­ка­ми че­рез сеть TCP/IP. Сер­вер – ком­пь­ю­тер, ко­то­рый пре­достав­ля­ет доступ к сво­ему же­ст­ко­му дис­ку. На нем ра­бо­та­ет при­клад­ная сер­вер­ная про­грам­ма, принимаю­щая за­про­сы из се­ти и транс­ли­рую­щая их в локаль­ные дис­ко­вые опе­ра­ции. Кли­ент – ком­пь­ю­тер, же­лаю­щий по­лу­чить доступ к уда­лен­но­му же­ст­ко­му дис­ку. На нем яд­ро Linux (для это­го оно долж­но быть со­б­ра­но с па­ра­мет­ром CONFIG_BLK_DEV_NBD) соз­да­ет в ка­та­ло­ге /dev на­бор фай­лов nbdN, ко­то­ры­ми бу­дут пред­став­лять­ся уда­лен­ные дис­ки. Как все это по­мо­жет в ра­бо­те с об­раз­ами? В QEMU есть спе­ци­аль­ная про­грам­ма qemu-nbd, по­зво­ляю­щая пред­ста­вить об­раз же­ст­ко­го дис­ка вир­ту­аль­ной ма­ши­ны уда­лен­ным же­ст­ким дис­ком. Сле­до­ва­тель­но, мож­но под­клю­чить об­раз к фай­лу, на­при­мер, /dev/nbd0, и ра­бо­тать с ним как с обыч­ным же­ст­ким дис­ком. Ес­ли NBD в яд­ре Linux со­б­ра­на в ви­де мо­ду­ля (на­при­мер, так сде­ла­но в Ubuntu 12.04 LTS), нуж­но не за­быть его за­гру­зить:

modprobe nbd max_part=16

qemu-nbd -c /dev/nbd0 /root/work/files/sysroot.img

partprobe /dev/nbd0

Теперь с помощью обычных средств для разметки дисков можно создать разделы. В данном случае достаточно простейшего варианта: один большой первичный раздел, занимающий все доступное пространство. Нужно только учесть, что в начале диска необходимо оставить 32,3 КБ для установки загрузчика.

parted /dev/nbd0 mklabel msdos

parted -a cylinder /dev/nbd0 mkpart primary 32.3k 1024

parted /dev/nbd0 set 1 boot on

В ка­та­ло­ге /dev поя­вил­ся но­вый файл nbd0p1. Это и есть толь­ко что соз­дан­ный раз­дел. Для пол­ной го­тов­но­сти к ра­бо­те оста­лось толь­ко от­фор­ма­ти­ро­вать его. Ка­кую фай­ло­вую сис­те­му вы­брать? Лю­бую. Глав­ное, что­бы яд­ро при за­груз­ке смог­ло ее опо­знать и смон­ти­ро­вать корневую фай­ло­вую сис­те­му. Опи­сан­ная вы­ше кон­фи­гу­ра­ция яд­ра тре­бу­ет ext4:

mkfs.ext4 /dev/nbd0p1

Те­перь ту­да нуж­но за­пи­сать корневую фай­ло­вую сис­те­му. Как это сде­лать? Тут то­же все стан­дарт­но для поль­зо­ва­те­ля Linux: смон­ти­ро­вать раз­дел в ка­кой-нибудь ка­та­лог (на­при­мер, мож­но соз­дать для этой це­ли /root/work/files/mnt) и ско­пи­ро­вать ту­да нуж­ные фай­лы.

mkdir /root/work/files/mnt

mount -t ext4 /dev/nbd0p1 /root/work/files/mnt/

cp -r /root/work/files/sysroot/* /root/work/files/mnt

Об­раз го­тов. Ос­та­лось толь­ко под­чис­тить «хво­сты»: раз­мон­ти­ро­вать раз­дел, осво­бо­дить файл nbd0 и вы­гру­зить мо­дуль nbd.

umount /root/work/files/mnt/

qemu-nbd -d /dev/nbd0

modprobe -r nbd

Настройка загрузчика

По­следний штрих – на­стро­ить и уста­но­вить за­груз­чик. Ес­ли сей­час по­про­бо­вать за­гру­зить KVM с об­ра­зом же­ст­ко­го дис­ка sysroot.img, ниче­го не по­лу­чит­ся. BIOS безуспеш­но по­про­бу­ет най­ти за­груз­чик, по­сле че­го про­цесс за­груз­ки оста­но­вит­ся. Мож­но про­ве­рить: kvm -m 512 /root/work/files/sysroot.img.

Дей­ст­ви­тель­но, даль­ше бес­конеч­но­го со­зер­цания со­об­щения Booting from Hard Disk [За­гру­жа­ет­ся с же­ст­ко­го дис­ка]... про­дви­нуть­ся не по­лу­ча­ет­ся.

К сча­стью, у KVM есть сред­ст­во во­об­ще обой­тись без за­груз­чи­ка: па­ра­метр kernel. Он по­зво­ля­ет ука­зать внешний файл об­раза яд­ра Linux, вме­сто то­го, что­бы до­ве­рять его по­иск за­груз­чи­ку на же­ст­ком дис­ке вир­ту­аль­ной ма­ши­ны:

cp /root/work/src/linux-3.2.25/arch/x86/boot/bzImage /root/work/files/bzImage

kvm -m 512 /root/work/files/sysroot.img -kernel /root/work/files/bzImage

За­гру­зи­лась! Поя­ви­лось при­гла­шение команд­ной стро­ки. Те­перь мож­но на­стро­ить Grub, что­бы в дальней­шем об­хо­дить­ся без внешнего яд­ра (внимание! Сле­дую­щие ко­ман­ды да­ют­ся в ОС, ко­то­рая за­пу­ще­на на KVM):

/usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg

/usr/sbin/grub-install /dev/sda

sync

Итак, за­груз­чик на­стро­ен, мож­но за­крыть вир­ту­аль­ную ма­ши­ну (про­сто за­крыть ок­но, ко­ман­да sync не даст по­те­рять дан­ные) и по­про­бо­вать за­пустить ее без па­ра­мет­ра kernel:

kvm -m 512 /root/work/files/sysroot.img

Загружается с жесткого диска!

Заключение

Спасибо всем, кто дочитал до конца. Хочется верить, что труд, вложенный в написание этой статьи, не пропал даром. Надеюсь, многие узнали что-то новое про внутреннее устройство Linux и стали чувствовать себя более уверенно в работе с любым дистрибутивом. А это, в свою очередь, послужит надежным фундаментом для поддержания интереса и дальнейшего углубления в удивительный и захватывающий мир открытого ПО. Кроме того, дистрибутив, сборка которого подробно описана в статье, не так уж бесполезен, как может показаться на первый взгляд. Например, он может служить прекрасным испытательным полигоном для экспериментов с ядром Linux. |

Персональные инструменты
купить
подписаться
Яндекс.Метрика