Теперь, когда все основные принципы объяснены, можно перейти к созданию зацикленного корневого устройства.
Создание зацикленного корневого устройства потребует от вас нескольких вещей.
Систему с работающим Linux-ом.
Способ скопировать большие файлы на DOS-раздел.
Наиболее важно иметь доступ к работающему Linux-у. Это необходимо по причине того, что зацикленное устройство может быть создано только в Linux-е. Это означает, что нельзя создать работающую машину с зацикленной корневой файловой системой из ничего. От этой Linux-системы потребуется возможность собрать на ней ядро.
После создания зацикленное устройство будет представлять из себя большой файл. Я использовал примерно 80 Мб файлов, но этого достаточно только, чтобы сделать Х-терминал, а возможно, если вы захотите чего-то большего, вам потребуется больше места. Этот файл должен быть скопирован на DOS-раздел, то есть придется использовать или сеть, или кучу флоппи-дисков.
Вам также понадобится следующее программное обеспечение:
LOADLIN версии 1.6 или новее
mount, поддерживающий зацикленные устройства
ядро, поддерживающее все необходимые условия.
Это все должно входить в последние инсталляции дистрибутивов Linux.
Я создал зацикленное устройство с использованием ядра версии 2.0.31, другие версии тоже должны работать, но они должны поддерживать все опции, перечисленные ниже.
Опции ядра, которые вам надо будет включить:
Поддержка электронных дисков (RAM disk support) (CONFIG_BLK_DEV_RAM).
Поддержка загрузочного электронного диска (Initial RAM disk (initrd) support) (CONFIG_BLK_DEV_INITRD).
Поддержка зацикленных устройств (Loop device support) (CONFIG_BLK_DEV_LOOP).
Поддержка файловой системы FAT (fat fs support) (CONFIG_FAT_FS).
Поддержка файловой системы MSDOS (msdos fs support) (CONFIG_MSDOS_FS).
Первые две опции - это сам электронный диск и загрузочный электронный диск. Следующая - это зацикленная файловая система. Последние две - это поддержка файловой системы msdos, которая необходима для подключения DOS-раздела.
Сборка ядра без модулей - это наиболее простой способ, но если вы все-таки решили использовать модули, это возможно, хотя я этого и не пробовал. Если вы используете модули, вы должны убедиться в том, что опции, используемые выше, встроены в ядро, а не собраны в виде модулей.
В зависимости от версии вашего ядра, вам, возможно, придется установить патч к ядру. Это очень простой патч, который разрешает использование зацикленной файловой системы в виде корневой.
Ядра версий до 2.0.0 - у меня нет информации по этому поводу.
Ядра версий 2.0.0 - 2.0.34 - вам придется использовать патч для ядер 2.0.х, приведенный ниже.
Ядра версий 2.0.35 - 2.0.x - патч не требуется.
Ядра версий 2.1.x - вам придется использовать патч для ядер 2.0.х или 2.2.х, приведенный ниже, в зависимости от конкретной версии ядра 2.1.x.
Ядра версий 2.2.0 - 2.2.10 - вам придется использовать патч для ядер 2.2.х, приведенный ниже.
Ядра версий 2.3.x - вам придется использовать патч для ядер 2.2.х, приведенный ниже.
Для ядер версий 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 << 8}, #endif { NULL, 0 } }; |
После того, как ядро настроено, его необходимо собрать в файл zImage (команда make zImage). Этот файл будет находиться в каталоге arch/i386/boot/zImage.
Загрузочный электронный диск проще всего создавать, как зацикленное устройство с самого начала. Вы должны делать это в качестве root-а. Список команд, которые вы должны запустить, приведен ниже. Они предполагают запуск из личного каталога root-а (/root).
mkdir /root/initrd dd if=/dev/zero of=initrd.img bs=1k count=1024 mke2fs -i 1024 -b 1024 -m 5 -F -v initrd.img mount initrd.img /root/initrd -t ext2 -o loop cd initrd [create the files] cd .. umount /root/initrd gzip -c -9 initrd.img > initrdgz.img |
Здесь производится несколько действий, которые можно вкратце описать так:
Создаем точку подключения загрузочного электронного диска (пустой каталог).
Создаем пустой файл необходимого размера. Я здесь использовал 1024 Кб, вам может понадобиться меньше или больше, в зависимости от содержимого (размер задается в последней опции).
Создаем файловую систему ext2 в пустом файле.
Подключаем этот файл к точке подключения, с использованием зацикленного устройства.
Переходим ко вновь подключенному зацикленному устройству.
Создадим там все необходимые файлы (см. ниже).
Выходим из подключенного зацикленного устройства.
Отключаем устройство.
Создаем компрессированную версию для дальнейшего использования.
Содержимое загрузочного электронного диска
На загрузочном диске нужно иметь все файлы, необходимые для запуска любых команд:
/linuxrc скрипт, который подключает файловую систему msdos (см. ниже).
/lib/* система динамических связей (dynamic linker) и библиотеки, необходимые программам.
/etc/* Кэш, используемый системой динамических связей (не очень нужен, но после этого перестают выдаваться жалобные сообщения).
/bin/* Интерпретатор оболочки (shell) (ash, потому что он меньше размером, чем bash. Программыmount и losetup для работы с DOS-диском и настройки зацикленных устройств.
/dev/* Устройства, которые будут использоваться. Вам потребуется устройство /dev/zero для библиотеки ld-linux.so, /dev/hda* для подключения msdos-диска и /dev/loop* для зацикленных устройств.
/mnt Пустой каталог для подключения msdos-диска.
Содержимое загрузочного электронного диска, которое я использовал, приведено ниже. Оно заняло примерно 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 |
Единственным сложным пунктом здесь являются устройства в каталоге dev. Используйте команду mknod, чтобы создать эти устройства, или используйте устройства в каталоге /dev, как шаблон для необходимых устройств.
Файл /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-пространством.
Если вы хотите иметь возможность писать на DOS-раздел, не будучи root-ом, когда все будет завершено, то вы должны использовать команду mount -n -t msdos /dev/hda1 /mnt -o uid=0,gid=0,umask=000,quiet, вместо приведенной выше. В этом режиме доступ к DOS-разделу буду исполняться так, как будто это делает root.
Корневое устройство, которое вы будете использовать - это файл linuxdsk.img. Его вам придется создать самим так же, как вы создавали загрузочный электронный диск, но значительно большего размера. Вы можете установить любой дистрибутив Linux, который вам понравится, на этот диск.
Наиболее простой путь для этого - скопировать существующую инсталляцию Linux в этот файл. Другой путь - установить туда Linux с дистрибутива. Предполагая, что вы это сделали, внесем некоторые незначительные изменения.
Файл /etc/fstab должен ссылаться на корневой раздел и swap-пространство через два зацикленных устройства, настроенных загрузочным электронным диском.
/dev/loop0 / ext2 defaults 1 1 /dev/loop1 swap swap defaults 1 1 |
Таким образом, вы будете уверены в том, что ядро не ошибется относительно реального местоположения корневой файловой системы. Также swap-пространство будет организовано обычным образом так, как будто используется обычный swap-раздел. Вы должны удалить все строки, ссылающиеся на корневое файловое устройство или swap-раздел.
Если хотите иметь возможность читать DOS-раздел под Linux-ом? вам придется внести еще несколько небольших изменений.
Создайте каталог /initrd, куда будет подключен загрузочный электронный диск после подключения зацикленной корневой файловой системы.
Создайте символьную ссылку /DOS, которая будет указывать на /initrd/mnt, куда, в свою очередь, будет подключен реальный DOS-раздел.
Добавьте строку в rc-файл, которая будет подключать диски. Там должна быть команда mount -f -t msdos /dev/hda1 /initrd/mnt, которая создаст 'поддельное' подключение DOS-раздела, чтобы программы (например, df) знали, что DOS-раздел подключен, и где его найти. Если вы использовали другие опции в файле /linuxrc, то, очевидно, вам придется их использовать и здесь.
Нет необходимости в том, чтобы иметь ядро Linux на этом корневом зацикленном устройстве, так как оно загружено ранее. Если вы используете модули, можете включить их в это устройство обычным образом.
Swap-устройство, которое вы будете использовать - это файл linuxswap.img. Swap-устройство очень просто создать. Создайте пустой файл так же, как делали это для загрузочного электронного диска, и затем запустите mkswap linuxswap.img для его инициализации.
Размер swap-устройства, которое вы будете использовать, зависит от ваших планов по использованию новой системы, но я бы рекомендовал его от 8 Мб до размера вашей оперативной памяти.
Файлы, которые будут нами использоваться, необходимо переписать на DOS-раздел.
В DOS-каталоге C:\LINUX должны находиться следующие файлы:
LINUXDSK.IMG Образ диска, который станет корневой файловой системой.
LINUXSWP.IMG Swap-пространство.
Загрузочный флоппи-диск, который мы будем использовать, является простым загрузочным диском DOS.
Он создается командой DOS format a: /s.
На этом диске вам надо создать файл AUTOEXEC.BAT (пример приведен ниже) и скопировать туда ядро, компрессированный загрузочный электронный диск и программу LOADLIN.
AUTOEXEC.BAT Автоматически запускаемый командный файл DOS.
LOADLIN.EXE Программа LOADLIN.
ZIMAGE Ядро Linux.
INITRDGZ.IMG Компрессированный образ загрузочного электронного диска.
В файле AUTOEXEC.BAT должна быть только одна строка.
\loadlin \zImage initrd=\initrdgz.img root=/dev/loop0 ro |
Здесь указано, какой образ ядра использовать, какой образ загрузочного электронного диска использовать, а также корневая файловая система, которая должна быть подключена "только для чтения".