The OpenNET Project / Index page

[ новости/++ | форум | wiki | теги ]

Использование loopback устройства для монитрования root-раздела в Linux (linux mount loop fs ext2fs boot)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: linux, mount, loop, fs, ext2fs, boot,  (найти похожие документы)
From: Андрей Рандрианасулу <randrik@mail.ru> Date: Mon, 28 Feb 2004 14:31:37 +0000 (UTC) Subject: Использование loopback устройства для монитрования root-раздела в Linux Оригинал: http://linuxshop.ru/linuxbegin/article636.html Вся система в одном файле. Андрей Рандрианасулу <randrik@mail.ru>, 12.12.2003 - Сижу я однажды после бессонной ночи в интернете, читаю 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 не сработала), но в виде модуля... И еще я прочитал о необходимости патчить ядро, для обеспечения возможности загрузки с loopback-устройства. Правда там самое новое из упомянутых ядер серии 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

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Ваш комментарий
Имя:         
E-Mail:      
Заголовок:
Текст:





  Закладки на сайте
  Проследить за страницей
Created 1996-2017 by Maxim Chirkov  
ДобавитьРекламаВебмастеруГИД  
Hosting by Ihor