Все о Linux. LinuxRSP.Ru
Альт Линукс СПТ 6.0 Сертификат ФСТЭК

Cвежие новости Linux и BSD, анонсы статей и книг прямо в почтовый ящик!
Подписаться письмом


 Сегодняшние новости:

В GIMP наконец-то появилась обработка с точностью 16 и 32 разряда на канал

В одном окне: GIMP 2.8

Релиз OpenBSD 5.1

HTML-редактор: BlueGriffon 1.5

Релиз Xfce 4.10

Команда Chromium представила кластер для автоматизации выявления уязвимостей

В Microsoft Office 15 будет обеспечена поддержка формата ODF 1.2

Анонсирован новый свободный анимационный фильм Tube

Обновление ядра: Linux 3.0.29, 3.2.16, 3.3.3

Представлен OpenSSH 6.0

Релиз графического редактора Pinta 1.2, претендующего на роль аналога Paint.NET

Вышел Firefox 12

Google прекращает поддержку Linux-версии приложения Picasa

Эмулятор приставок: Mednafen 0.9.21-wip

Линус Торвальдс получил премию Millennium Technology Prize 2012

Canonical не заинтересована в участии в разработке ядра Linux

Распределенные вычисления: BOINC 7.0

Google

 Новые статьи :

Передача снапшота ZFS по сети

Правила хорошего тона: SSH

Некоторые рассуждения о защите от ddos на примере защиты от SSL denial of service attack

Быстрый проброс портов на шлюзе во внутреннюю сеть или на другой хост. Быстро NAT'им порты. rinetd.

NAT'им отдельные порты или "а что делать, если мой веб-сервер внезапно переехал на другую машину". Проброс портов в локалке на шлюзе наружу.

Как справляться с запланированной недоступностью веб-сайта

Архитектура Google 2011

Мониторинг Nginx с помощью MRTG

Решение проблем при использовании "1c предприятие" 8.2 в Linux

25 правил .htaccess, которые должен знать каждый web-разработчик

Централизованное резервное копирование данных Windows и *nix серверов средствами Bacula

Краткое руководство по GNOME Shell в Ubuntu 11.10

Advanced Bash-Scripting Guide Искусство программирования на языке сценариев командной оболочки

   Дистрибутивы и атрибутика



DeveloperWorks Россия





Rambler's Top100


 
 

Вся система в одном файле. Часть 1

Сижу я однажды после бессонной ночи в интернете, читаю HOWTO. И попадается мне очень интересная HOWTO-шка под названием "Loopback-Root-FS (использование loopback устройства Linux для создания файловой системы Linux, которая может запускаться из DOS-раздела без изменения системы разделов)" О как. Там идет речь о создании корневой файловой системы ext2 внутри файла, лежащего на разделе MS-DOS. И о запуске всей системы с помощью 3 файлов: загрузчика LOADLIN, ядра и этого файла с ext2 внутри.... Правда, там еще свап предлагают создать.... Тоже в файле на разделе DOS. Ну конечно я свап создал ... на 16 метров :) Чисто на всякий пожарный. Однако по ходу дела возникло много вопросов, в ходе решения которых я узнал много интересного...

Итак, в начале я создал командой dd все необходимые файлы:

#dd if=/dev/zero of=/root/initrd.img bs=1024 count=4096
(Это - заполненный нулями файл размером в 4 Мб, который вскоре будет нести в себе файловую систему Ext2 для Initial RAM drive).
#dd if=/dev/zero of=/root/linuxdsk.img bs=1024 count=16384
(Тут будет корневая ФС, размер [count=], разумеется, нужно выбирать разумно, исходя из того, сколько места есть на диске и сколько места хочется получить внутри файла когда там будет создана файловая система... Я "навскидку" решил, что мне для тренировки хватит 16 Мб)
#dd if=/dev/zero of=/root/linuxswp.img bs=1024 count=16384
(Тот самый свап... При наличии 128 Мб ОЗУ и отсутствии Х-ов он может быть и таким маленьким... Хотя можно создать и больший, если надо.)

Такие маленькие файлы, заполненные нулями, создаются на PII-420 с быстрым современным HDD очень недолго. Однако при создании вскоре (интереса для) 5Гб файла мне пришлось пойти попить чайку :)

Теперь, когда файлы созданы, в них создается файловая система (в этом случае - ext2, потом мне пришлось создавать в основном системном файле ext3, но об этом позже).
# cd /root
# mke2fs -i 1024 -b 1024 -m 5 -F -v initrd.img
# mke2fs -i 1024 -b 1024 -m 5 -F -v linuxdsk.img
# mkswap linuxswp.img

Значения всех опций можно узнать в man-странице mke2fs

Теперь пора примонтировать созданные файлы:

# mount -o loop /root/linixdsk.img /mnt/disk
(Монтируем как loopback-устройство к каталогу /mnt/disk)
# mount -o loop /root/initrd.img /root/initrd
(Разумеется, я этот каталог сначала создал в /root )

Захожу в каталог /mnt/disk и вижу там папку lost+found :) Сюрприз...
В /root/initrd она тоже есть. Ладно, она же ведь пока пустая и ничем не мешает :)
Теперь пора наполнить содержимым обе файловые системы - скопировать туда необходимые файлы и каталоги.
Начать видимо следует с initrd.img, смонтированного у меня к /root/initrd, т.к. в HOWTO был так описан процесс загрузки всей этой системы:

---cut on-------
Последовательность загрузки Linux

Чтобы понять, как загрузочный электронный диск работает в процессе загрузки системы, изучим порядок событий при загрузке системы.

1. Ядро загружается в память. Эту операцию производит LILO или LOADLIN. В этот момент выводится сообщение Loading...
2. Образ электронного диска загружается в память, это тоже делает LILO или LOADLIN. В этот момент также выводится сообщение Loading...
3. Производится инициализация ядра, включая обработку опций командной строки и подключение электронного диска в виде корневой файловой системы.
4. На загрузочном электронном диске запускается программа /linuxrc.
5. Корневое устройство переключается в соответствии с параметром ядра.
6. Запускается программа /etc/init, которая уже производит настраиваемую пользователем последовательность загрузки.

Это упрощенное описание того, что происходит на самом деле, но этого достаточно, чтобы описать, как запускается ядро и как используется электронный диск.
---cut off----

Ну значит поехали... Там же чуть ниже приведен ПРИМЕР содержимого загрузочного эл. диска (aka Initial RAM drive)

---cut on----
Содержимое загрузочного электронного диска, которое я использовал, приведено ниже. Оно заняло примерно 800 Кб, если принимать в расчет излишки файловой системы.

total 18
drwxr-xr-x 2 root root 1024 Jun 2 13:57 bin
drwxr-xr-x 2 root root 1024 Jun 2 13:47 dev
drwxr-xr-x 2 root root 1024 May 20 07:43 etc
drwxr-xr-x 2 root root 1024 May 27 07:57 lib
-rwxr-xr-x 1 root root 964 Jun 3 08:47 linuxrc
drwxr-xr-x 2 root root 12288 May 27 08:08 lost+found
drwxr-xr-x 2 root root 1024 Jun 2 14:16 mnt

./bin:
total 168
-rwxr-xr-x 1 root root 60880 May 27 07:56 ash
-rwxr-xr-x 1 root root 5484 May 27 07:56 losetup
-rwsr-xr-x 1 root root 28216 May 27 07:56 mount
lrwxrwxrwx 1 root root 3 May 27 08:08 sh -> ash

./dev:
total 0
brw-r--r-- 1 root root 3, 0 May 20 07:43 hda
brw-r--r-- 1 root root 3, 1 May 20 07:43 hda1
brw-r--r-- 1 root root 3, 2 Jun 2 13:46 hda2
brw-r--r-- 1 root root 3, 3 Jun 2 13:46 hda3
brw-r--r-- 1 root root 7, 0 May 20 07:43 loop0
brw-r--r-- 1 root root 7, 1 Jun 2 13:47 loop1
crw-r--r-- 1 root root 1, 3 May 20 07:42 null
crw-r--r-- 1 root root 5, 0 May 20 07:43 tty
crw-r--r-- 1 root root 4, 1 May 20 07:43 tty1
crw-r--r-- 1 root root 1, 5 May 20 07:42 zero

./etc:
total 3
-rw-r--r-- 1 root root 2539 May 20 07:43 ld.so.cache

./lib:
total 649
lrwxrwxrwx 1 root root 18 May 27 08:08 ld-linux.so.1 -> ld-linux.so.1.7.14
-rwxr-xr-x 1 root root 21367 May 20 07:44 ld-linux.so.1.7.14
lrwxrwxrwx 1 root root 14 May 27 08:08 libc.so.5 -> libc.so.5.3.12
-rwxr-xr-x 1 root root 583795 May 20 07:44 libc.so.5.3.12

./lost+found:
total 0

./mnt:
total 0
---cut off----

Приняв это за основу, я скопировал актуальные для моей системы версии файлов.... Опа... Со времени написания HOWTO прошло почти 4 года, и "начинка" заняла почти 2.5 мега... Разумеется, с этим можно бороться, призвав на помощь к примеру "The Linux Bootdisk HOWTO" раздел "Уменьшение размера корневой файловой системы" (для нас это будет размер первоначальной корневой системы, т.к. корневой впоследствии станет другая, еще пока даже не заполненная система в файле linuxdsk.img) Кстати, Bootdisk HOWTO мне очень пригодилось, когда я создавал основную структуру каталогов и файлов в linuxdsk.img .... Сколько я нового и интересного узнал о старте Linux-системы... Но это позже, т.к. в начале я читал не очень внимательно (за что поплатился чуть позже).

В общем, я призвал на помощь mc и копировал, копировал, копировал.... Чтобы узнать, кому какие библиотеки нужны, я вызывал команду ldd и получал список требуемых библиотек и их расположение.
Я даже не забыл создать внутри будущей корневой ФС файлик /etc/fstab :

#cat /mnt/disk/etc/fstab

/dev/loop0 / ext2 defaults 1 1
/dev/loop1 swap swap defaults 1 1

Уф. Через некоторое время я, кажется, всё упаковал и в /root/initrd, и в/mnt/disk (т.е. в файлы /root/initrd.img и /root/linuxdsk.img, подключенные сейчас туда). Пора писать скрипт linuxrc и готовить ядро ...

Черт! Ядро... Срочно прочитав секцию "Создаём ядро Linux" Loopback-Root-FS HOWTO, я понял, что при очередной недавней компиляции ядра я забыл вкомпилировать в него поддержку loopback FS. Она была (иначе бы опция -o loop команды mount не сработала), но в виде модуля... И еще я прочитал о необходимости патчить ядро, для обеспечения возможности загрузки с oopback-устройства. Правда там самое новое из упомянутых ядер серии 2.3.х у меня же 2.4.21 с патчем для поддержки xfs. Полез в свой /usr/src/linux и начал там поиск... Оказалось что со времен серии 2.2.х некоторые описания структур ядра "переехали" - я, например, нашел список устройств для загрузки в
usr/src/linux/init/do_mounts.c :

---cut on---

static struct dev_name_struct {
const char *name;
const int num;
} root_dev_names[] __initdata = {
{ "nfs", 0x00ff },
{ "hda", 0x0300 },
{ "hdb", 0x0340 },
{ "loop", 0x0700 },
{ "hdc", 0x1600 },
{ "hdd", 0x1640 },
{ "hde", 0x2100 },
{ "hdf", 0x2140 },
{ "hdg", 0x2200 },
{ "hdh", 0x2240 },
{ "hdi", 0x3800 },
{ "hdj", 0x3840 },
{ "hdk", 0x3900 },
{ "hdl", 0x3940 },
{ "hdm", 0x5800 },
{ "hdn", 0x5840 },
{ "hdo", 0x5900 },

---cut off---

Там очень длинная структура, желающие могут ознакомиться....

А в HOWTO рекомендовалось делать так

---cut on----
Для ядер версий 2.0.x в файл /init/main.c надо добавить одну строку, в соответствии с уже измененной версией, приведенной ниже. В строке, которую надо добавить написано "loop", 0x0700.

static void parse_root_dev(char * line)
{
int base = 0;
static struct dev_name_struct {
const char *name;
const int num;
} devices[] = {
{ "nfs", 0x00ff },
{ "loop", 0x0700 },
{ "hda", 0x0300 },

...

{ "sonycd", 0x1800 },
{ NULL, 0 }
};

...

}

Для ядер версий 2.2.x в файл /init/main.c надо добавить три строки, в соответствии с уже измененной версией, приведенной ниже. Надо добавить строку, в которой написано "loop", 0x0700, а также предшествующую и следующую за ней:

static struct dev_name_struct {
const char *name;
const int num;
} root_dev_names[] __initdata = {
#ifdef CONFIG_ROOT_NFS
{ "nfs", 0x00ff },
#endif
#ifdef CONFIG_BLK_DEV_LOOP
{ "loop", 0x0700 },
#endif
#ifdef CONFIG_BLK_DEV_IDE
{ "hda", 0x0300 },

...

{ "ddv", DDV_MAJOR /kernel/fs/ [не исключаю, что модули можно и кучей свалить в /lib/modules, только зачем создавать бардак?]. Правда, модуль loop.o лежит среди блочных {block} устройств, но ведь никто не мешает засунуть в InitialRAM drive все, что нужно для монтирования корневой ФС..... К примеру драйверы USB для монтирования корня с флешки....

Скопировал из своей действующей системы все нужные модули в соотв. каталог /root/initrd . Там у меня до сих пор болтался примонтированный файл /root/initrd.img. Теперь принимаемся за скрипт /linuxrc (тут корень уже для загрузившегося с этим RAM-диском ядра...).

В HOWTO был приведен пример:

---cut on---

Файл /linuxrc

Файл/linuxrc на загрузочном электронном диске нужен для того, чтобы произвести все приготовления, необходимые для подключения зацикленного устройства как корневого.

Скрипт, приведенный ниже пытается подключить /dev/hda1 как раздел msdos, и если это происходит удачно, то он настраивает файлы /linux/linuxdsk.img как /dev/loop0 и /linux/linuxswp.img как /dev/loop1.

#!/bin/sh

echo INITRD: Trying to mount /dev/hda1 as msdos
# echo INITRD: Попытка подключить /dev/hda1 как msdos

if /bin/mount -n -t msdos /dev/hda1 /mnt; then

echo INITRD: Mounted OK
# echo INITRD: Подключение успешно
/bin/losetup /dev/loop0 /mnt/linux/linuxdsk.img
/bin/losetup /dev/loop1 /mnt/linux/linuxswp.img
exit 0

else

echo INITRD: Mount failed
# echo INITRD: Подключение не удалось
exit 1

fi

Первое устройство /dev/loop0 станет корневым, а второе - /dev/loop1 - станет swap-пространством.

----cut off----

Я немного подредактировал скрипт под свою таблицу разделов (я решил поместить файлы linuxdsk.img и linuxswp.img в каталог /linux-loop на корневом в текущий момент устройстве /dev/hda5). Исправить тип в команде mount минутное дело. Очень быстро скрипт был надлежащим образом записан, проверен, закомментирован русским языком :).

Теперь отмонтируем примонтированные устройства
# umount /mnt/disk
# umount /root/initrd

Теперь можно сжать образ загрузочного RAM-диска.
#cd root
#gzip -c -9 initrd.img > initrdgz.img
(все уже поняли, что файлы могут называться как угодно и подключаться куда угодно, однако файл RAM-диска, похоже, должен иметь имя initrd*.img, что легко получить, скопировав его в /boot с нужным именем. Да, стоит внимательно посмотреть, что там еще в /boot есть... И вообще, работать под рутом надо аккуратно.... Однажды в ходе этой (многочасовой) эпопеи я чуть не остался без всех своих модулей в /lib/modules/ - просто вместо F5 в mc нажал F6. Хорошо, опомнился вовремя.)

Теперь осталось подготовить все для загрузки свеженабранной "с бору по сосенке" :) Linux-системы.

linuxdsk.img идет в /linux-loop, туда же отправляется linuxswp.img
Ядро у меня уже лежит в /boot (грузить вся я буду с помощью lilo)
Кладем туда же в /boot наш initrdgz.img

Модифицируем /etc/lilo.conf, добавляя туда секцию вида:

---cut on ---
image=/boot/bzImage-ran0
label=loop-i586
initrd=/boot/initrdgz.img
vga=normal
append="root=/dev/loop0"
read-only
---cut off---

ПРЕДУПРЕЖДЕНИЕ!!! Тут я совершил ошибку, видимо... Слепо скопировал "как написано было". Ядро, видимо, получило сначала команду append="root=/dev/loop0", и молча проигнорировало наличие RAM-диска, вывалившись в итоге с kernel panic по поводу невозможности смонтировать корневую ФС. Полез читать /usr/src/linux/Documentation/initrd.txt и man initrd. Понял, что существуют два механизма смены корневой ФС в процессе работы. Мне удалось реализовать только более старый вариант, через proc filesystem.

Выдержка из man initrd:

---cut on----

СМЕНА НОРМАЛЬНОЙ КОРНЕВОЙ ФАЙЛОВОЙ СИСТЕМЫ
По умолчанию, конфигурация ядра (например, установленная в файле ядра с помощью rdev или на этапе компиляции ядра) или установки загрузчика используются определения нормальной корневой файловой системы.

Для NFS-монтируемой нормальной корневой файловой системы нужно использовать загрузочные опции nfs_root_name и nfs_root_addrs для задания установок NFS. За дополнительной информацией по NSF-монтируемой корневой ФС обращайтесь к файлу документации к ядру nfsroot.txt. Также дополнительная информация по установкам корневой файловой системы содержится в документации к LILO и LOADLIN.

Кроме того, /linuxrc может сменить нормальное корневое устройство. Для того, чтобы /linuxrc сменил это устройство, должен быть подмонтирован каталог /proc. После монтирования /proc, /linuxrc сменяет нормальное корневое устройство, записывая установки в файлы proc /proc/sys/kernel/real-root-dev, /proc/sys/kernel/nfs-root-name, и /proc/sys/kernel/nfs-root-addrs. Что касается физического корневого устройства, оно меняется, если /linuxrc записывает номер нового устройства корневой файловой системы в /proc/sys/kernel/real-root-dev. Для корневой файловой системы NSF корневое устройство меняется, если /linuxrc записывает установки NSF в файлы /proc/sys/kernel/nfs-root-name и /proc/sys/kernel/nfs-root-addrs, а затем записывает 0xff (например,номер псевдо-NFS-устройства) в файл /proc/sys/kernel/real-root-dev.

Так, например, следующие команды изменят нормальное корневое устройство на /dev/hdb1:

echo 0x365 >/proc/sys/kernel/real-root-dev

В качестве примера для NSF, следующие команды изменят нормальное корневое устройство на каталог NSF /var/nfsroot на локальном сетевом NSF-сервере с IP-адресом 193.8.232.7 для системы с IP-адресом
193.8.232.7 и именем 'idefix':

echo /var/nfsroot >/proc/sys/kernel/nfs-root-name
echo 193.8.232.2:193.8.232.7::255.255.255.0:idefix
>/proc/sys/kernel/nfs-root-addrs
echo 255 >/proc/sys/kernel/real-root-dev

---cut off---

Мне оставалось только догадаться, что в моем случае для /dev/loop0 нужно написать строчку вида echo 0x700 >/proc/sys/kernel/real-root-dev .

Я прописал монтирование /proc и эту строку в /linuxrc, убрал в lilo.conf строчку 'append' и система загрузилась.... Почти. Дальше у меня была долгая пляска вокруг init, однако мне так хотелось спать, что я решил оставить все разборки с init на завтра.... Да и этот текст не стоит IMHO делать очень длинным...Насчет init я как-нибудь попозже напишу.

Я пользовался следующими документами:
1. Bootdisk-HOWTO (как создать загрузочную дискету под Линукс)
2. Loopback-Root-FS (использование loopback устройства Linux, для создания файловой системы Linux, которая может запускаться из DOS-раздела без изменения системы разделов)
3. Документация ядра 2.4.21
4. man initrd

Андрей Рандрианасулу


      

Связь | О проекте LinuxRSP | Реклама | О Linux
© 1999-2012 LinuxRSP


Реклама:
Обвес Lorinser