форумы  рассылка  download Перейти на новую версию сайта:
www.slackware.ru
Искать    где:    






    
slackware.ru > Документация > Применение начального RAM диска ID:654
 
2003-08-06 hunter
Применение начального RAM диска

Применение начального RAM диска (initrd)

Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch> and Hans Lermen <lermen@fgan.de>

Предисловие переводчика

Предлагаемый документ является переводом initrd.txt входящего в состав исходных текстов ядра Linux. Не смотря, на свою доступность, распространенность и почтенный возраст (функциональность initrd включена в ядро с версии 1.3.73) документ является актуальным. К настоящему моменту, практически, все изготовители дистрибутивов Linux-систем используют initrd для первоначальной загрузки системы и запуска процедуры инсталляции (redhat'образные дистрибутивы, afaik, вообще используют initrd для штатной загрузки системы). Кроме этого, initrd позволяет оперативно и легко создавать свои собственные загрузочные диски с узкоспециализированными задачами (напр., диски аварийного восстановления системы, тестирования и диагностики оборудования компьютера и локальных сетей, антивирусной проверки файловых систем и пр.), поддерживающими широкий спектр периферийного оборудования.

Перевод был доведен до логического завершения в надежде, что спровоцирует у ``русскоязычной'' части пользователей желание к более глубокому пониманю методов загрузки Linux-систем. Естественно, краткое введение в возможности initrd и способы его использования лишь дополняет документы касающиеся общей процедуры загрузки Linux, ссылки на которые следуют далее по тексту. Кроме этих документов не менее полезными являются: Bootdisks-HOWTO, документация в составе lilo и syslinux.

--

Sincerely yours,

hunter

Предисловие

initrd обеспечивает возможность загрузки RAM диска начальным загрузчиком (boot loader). Данный RAM диск, может быть смонтирован в качестве корневой файловой системы (root filesystem) с которой можно исполнять программы. Впоследствии, уже с другого устройства, можно смонтировать новую файловую систему. После чего, предыдущая корневая файловая система (с initrd) перемещается в отдельную директорию и позже может быть демонтирована.

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

Данный документ дает краткий обзор использования initrd. Более подробное описание процесса загрузки системы можно найти в [1].

Работа

При использовании initrd, обычно, система загружается следующим образом:

  1. начальный загрузчик загружает ядро и начальный RAM диск
  2. ядро преобразует initrd в ``нормальный'' RAM диск и освобождает память, занимаемую initrd
  3. initrd монтируется как корневая файловая система с доступом по чтению записи
  4. исполняется /linuxrc (это может быть любой исполняемый файл, включая скрипт командного процессора. Данный файл исполняется с uid 0 и по сути включает в себя все, что может выполнить обычный init)
  5. linuxrc монтирует ``реальную'' корневую файловую систему
  6. с помощью системного вызова pivot_root, linuxrc помещает корневую файловую систему в корневую директорию
  7. на корневой файловой системе выполняется обычная процедура загрузки (напр., вызов /sbin/init)
  8. файловая система initrd удаляется
Отметим, что смена корневой директории не включает её демонтирование. Следовательно, при выполнении данной процедуры можно сохранить процессы запущенные с файловой системы initrd.

Опции командной строки загрузки (boot command-line)

initrd добавил следующие опции:

initrd=<path>
(напр., для LOADLIN) загружает указанный файл как начальный RAM диск. При использовании LILO имеется возможность указать файл образа RAM диска в /etc/lilo.conf с помощью переменной INITRD
noinitrd
данные из initrd обрабатываются, но не преобразуются в RAM диск, а вместо этого монтируется ``нормальная'' файловая система. Данные из initrd можно читать из /dev/initrd. Отметим, что, в этом случае, данные в initrd могут быть в любой структуре и нет необходимости иметь образ файловой системы. Эта опция используется, главным образом, для отладки.
Примечание. устройство /dev/initrd доступно только по чтению и может использоваться только один раз. Как только последний процесс закроет устройство, все данные освобождают память и /dev/initrd больше не может быть открыто.
root=/dev/ram0
(при отсутствии devfs)
root=/dev/rd/0
(при наличии devfs) initrd монтируется как корневое устройство, далее следует нормальная процедура загрузки системы с сохранением RAM диска корневым.

Установка

Во-первых, создается директория для файловой системы initrd на ``нормальной'' корневой файловой системе, напр.:

# mkdir /initrd

Имя директории безразлично. Подробности можно найти в руководстве (man page) pivot_root(2).

Если в процессе загрузки создается корневая файловая система (напр., если создается инсталляционная дискета), то процедура создания корневой файловой системы должна создавать директорию /initrd.

В случаях, когда initrd не монтируется, его содержимое остается доступным если создано следующее устройство (не работает при использовании devfs):

# mknod /dev/initrd b 1 250

# chmod 400 /dev/initrd

Во-вторых, ядро должно быть собрано с поддержкой RAM диска. В ядро также должны быть встроены все компоненты необходимые для выполнения программ с initrd (напр., поддержка форматов исполняемых файлов и файловых систем).

В-третьих, создается образ RAM диска. Это делается путем создания файловой системы на блочном устройстве, копирования на неё нужных файлов, а затем копирования содержимого блочного устройства в файл initrd. С последними версиями ядра для этого подходят три типа устройств:

  • гибкий (floppy) диск (работает везде, но ужасно медленный)
  • RAM диск (быстрый, но занимает физическую память)
  • loopback устройство (наиболее элегантное решение)
Мы рассмотрим метод, использующий loopback устройство:

  1. убедитесь, что поддержка loopback встроена в ядро
  2. создайте пустую файловую систему подходящего размера, напр.:

    # dd if=/dev/zero of=initrd bs=300k count=1

    # mke2fs -F -m0 -b 1024 initrd

    (если пространство - является критическим параметром, можно попробовать Minix вместо Ext2)

    Примечание. Вследствие других проблем ядра, вы должны использовать размер блока файловой системы 1024 байта. Если использовать другие значения, ядро будет не в состоянии смонтировать initrd при загрузке, что приведет к kernel panic.

  3. смонтируйте файловую систему, напр.:

    # mount -t ext2 -o loop initrd /mnt

  4. создайте устройство console (нет необходимости при использовании devfs, но не повредит в любом случае):

    # mkdir /mnt/dev

    # mknod /mnt/dev/console c 5 1

  5. скопируйте все файлы, которые необходимы для правильного использования initrd. Не забудьте про наиболее важный файл /linuxrc.

    Примечание. Атрибуты /linuxrc должны включать ``x'' (execute)

  6. корректную работу среды initrd зачастую можно проверить даже без перезагрузки с помощью команды:

    # chroot /mnt /linuxrc

    Конечно, это ограничивает деятельность initrd тем, что он не может интерферировать с состоянием основной системы (напр., переконфигурируя сетевые интерфейсы, перезаписывая устройства, попытками запустить уже работающие сервисы-демоны, и т.д. Однако, как правило, использовать pivot_root в такой среде удается).

  7. демонтируйте файловую систему:

    # umount /mnt

  8. теперь initrd в файле ``initrd''. Опционально, его можно сжать:

    # gzip -9 initrd

Для экспериментов с initrd, можно попробовать создать дискету аварийного восстановления и добавить только символическую ссылку /linuxrc на /bin/sh. Или же, можно поэкспериментировать с newlib [2] для создания initrd малого размера.

Последнее, теперь можно загрузить ядро и initrd. Почти все начальные загрузчики Linux поддерживают initrd. Поскольку процесс загрузки все еще совместим со старым механизмом, допустимы следующие параметры командной строки загрузки:

root=/dev/ram0 init=/linuxrc rw

если не используется devfs, или:

root=/dev/rd/0 init=/linuxrc rw

если используется devfs. (rw необходимо если нужен доступ по записи к файловой системе initrd).

При использовании LOADLIN, просто выполните:

LOADLIN <kernel> initrd=<disk_image>

напр.:

LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 init=/linuxrc rw

При использовании LILO, добавьте опцию INITRD=<path> в /etc/lilo.conf или в разделе глобальных параметров или в разделе параметров соответствующего ядра и передайте ему опции с использованием APPEND, напр.:

image = /bzImage

initrd = /boot/initrd.gz

append = "root=/dev/ram0 init=/linuxrc rw"

и выполните /sbin/lilo .

Для других загрузчиков, смотрите соответствующую документацию.

Теперь вы можете загружать и наслаждаться initrd.

Смена корневого устройства

Выполнив свои обязанности, linuxrc обычно меняет корневое устройство и переходит к запуску Linux системы на ``реальном'' корневом устройстве.

Процедура включает в себя следующие шаги:

  • монтирование новой корневой файловой системы
  • переход на новую корневую файловую систему
  • удаление доступа к старой (initrd) корневой файловой системе
  • демонтирование файловой системы initrd и освобождение RAM диска
Монтирование новой корневой файловой системы делается легко: достаточно просто смонтировать ее в какой-либо директории текущей корневой файловой системы. Например:

# mkdir /new-root

# mount -o ro /dev/hda1 /new-root

Смена корневого устройства выполняется системным вызовом pivot_root, который также доступен через утилиту pivot_root (см. pivot_root(8); pivot_root распространяется в составе util-linux версии не ниже 2.10h [3]). pivot_root перемещает текущее корневое устройство в директорию на новом устройстве, а новое корневое устройство кладет на его место. Директория для прежнего корневого устройства должна существовать до вызова pivot_root. Например:

# cd /new-root

# mkdir initrd

# pivot_root . initrd

Сейчас, процесс linuxrc все еще имеет доступ к прежней корневой файловой системе через исполняемые модули, разделяемые библиотеки, устройства standard input/output/error, и их текущие корневые директории. Все эти связи и ссылки отбрасываются следующей командой:

# exec chroot . what-follows <dev/console >dev/console 2>&1

Где, what-follows - программа с новой файловой системы, напр., /sbin/init .1

Если новая файловая система будет использовать devfs и не имеет действующей директории /dev, devfs должна быть смонтирована до вызова chroot с целью создания /dev/console.

Примечание. особенности применения pivot_root могут меняться со временем. Чтобы быть уверенным в сохранении совместимости, следует просмотреть следующие пункты:

  • перед вызовом pivot_root текущая директория вызова процессов должна указывать на новую корневую директорию
  • используйте ``.'' в качестве первого аргумента и относительные пути директорий для старой файловой системы в качестве второго аргумента
  • программа chroot должна быть доступна в старой и новой файловых системах
  • смещайтесь в новую корневую систему (chroot) в последнюю очередь
  • используйте относительные пути для /dev/console в команде exec
Теперь можно демонтировать initrd и освободить память занятую RAM диском:

# umount /initrd

# blockdev -flushbufs /dev/ram0 # /dev/rd/0 if using devfs

Можно также использовать initrd с корневой файловой системой монтируемой по NFS, см. pivot_root(8).

Примечание. Если linuxrc или другая программа исполненная из неё завершится по какой-либо причине, то будет вызван старый механизм change_root (см. раздел ``Устаревший механизм смены корневой системы'')

Сценарии использования

Главной мотивацией для реализации initrd было стремление следовать модульной конфигурации ядра при инсталляции системы. При этом данная процедура работает следующим образом:

  1. система стартует с дискеты или другого носителя с минимальным ядром (напр., поддержка RAM диска, initrd, a.out и ext2) и загружает initrd
  2. /linuxrc определяет что требуется для: (a) монтирования ``реальной'' корневой файловой системы (т.е. тип устройств, драйвера устройств, файловая система) и (b) носителя дистрибутива (напр., CD-ROM, сеть, стриммер, ... ). Это можно осуществить через запрос пользователя, автоматическое определение конфигурации или с использованием гибридного подхода.
  3. /linuxrc загружает необходимые модули ядра
  4. /linuxrc создает и заполняет корневую файловую систему (это еще не является системой готовой к использованию)
  5. /linuxrc вызывает pivot_root для смены корневой файловой системы и исполняет, через chroot, программу которая продолжает установку
  6. устанавливается начальный загрузчик
  7. начальный загрузчик конфигурируется для загрузки initrd с набором модулей которые были использованы при формировании системы (напр., /initrd можно модифицировать, затем демонтировать и записать его образ с /dev/ram0 или /dev/rd/0 в файл)
  8. теперь система в состоянии стартовать и можно выполнить дополнительные задачи установки
Здесь ключевая роль initrd заключается в повторном использовании информации о конфигурации в процессе нормальной работы системы, не требующее применения раздутого ``многоцелевого'' ядра или перекомпиляции и сборки нового ядра.

Второй сценарий, для инсталляций, где Linux работает на системах с различной аппаратной конфигурацией в едином административном домене. В таких случаях желательно сформировать небольшой набор ядер (в идеальном случае - единственное), а системозависимую часть конфигурационной информации сократить до минимума насколько это возможно. В данном случае, можно сформировать общий initrd со всеми нужными модулями. Разными будут только /linuxrc или файлы считываемые им.

Третий сценарий больше подходит для дисков аварийного восстановления, поскольку такая информация, как расположение раздела с корневой файловой системой на момент загрузки нельзя обеспечить заранее, но система, загрузившись с initrd может вызвать диалог с пользователем, а также выполнить некоторые очевидные проверки (или даже автоматическое определение конфигурации в той или иной форме).

Последний, но не завершающий список, сценарий, распространители дистрибутивов на CD-ROM могут использовать initrd для улучшения процедуры инсталляции с CD, напр., использовать стартовую дискету и связать с ней, через initrd, стартовый RAM диск большого размера с CD; или стартовать через начальный загрузчик типа LOADLIN или непосредственно с CD, а затем загрузить RAM диск с CD без дискет.

Устаревший механизм смены корневой системы

До введения pivot_root использовался следующий механизм. Современные версии ядра все еще поддерживают его, но вам не следует полагаться на то , что его наличие сохраниться.

Данный механизм монтирует ``реальное'' корневое устройство (т.е. устройство установленное командой rdev в образе ядра или опцией root=... командной строки загрузки) в качестве корневой файловой системы в момент завершения работы linuxrc. Затем, файловая система initrd демонтируется, или, если она все еще занята, перемещается в директорию /initrd, если она существует на новой корневой файловой системе.

Для использования данного механизма не нужно указывать опции загрузки root, init или rw. (Если указаны, они влияют только на реальную корневую файловую систему, а не на initrd.)

Если файловая система /proc смонтирована, то ``реальное'' корневое устройство можно сменить включив в linuxrc запись номера устройства в специальный файл /proc/sys/kernel/real-root-dev, напр.:

# echo 0x301 >/proc/sys/kernel/real-root-dev

Отметим, что данный механизм несовместив с NFS или подобными ей файловыми системами.

Этот устаревший, нерекомендуемый, способ общепринято называть "change_root", в то время, как новый поддерживаемый механизм называется "pivot_root".

Bibliography

1
Almesberger, Werner; "Booting Linux: The History and the Future" ftp://icaftp.epfl.ch/pub/people/almesber/booting/bootinglinux-current.ps.gz

2
Пакет newlib (experimental), с примерами initrd ftp://icaftp.epfl.ch/pub/people/almesber/misc/newlib-linux/

3
Brouwer, Andries; "util-linux: Miscellaneous utilities for Linux" ftp://ftp.win.tue.nl/pub/linux-local/utils/util-linux/



Footnotes

...1
Прим. перев. Очень подробно про демонтирование файловой системы initrd можно прочитать в pivot_root(8). Данная процедура имеет свои особенности, и весьма важные. Простой вызов /sbin/init произведет загрузку системы, но может не позволить полностью освободить файловую систему initrd и демонтировать её .

hunter
2003-08-06



оставить комментарий
Как Вы оцениваете эту статью? 
коментарии к статье

 развернуть комментарии (всего 0,персональных 0)