From: Dmitrijj Kulikovskijj <crazy.format@gmail.com.>
Date: Mon, 4 Jun 2007 13:01:37 +0000 (UTC)
Subject: Общее представление о initrd (Initial RAM disk)
Начальный RAM диск для загрузки Linux (initrd) это временная корневая
файловая система, которая монтируется в процессе загрузки системы в
оперативную память для поддержки 2х уровневой модели загрузки. Initrd
состоит из различных исполняемых файлов и драйверов, которые позволяют
смонтировать настоящую корневую файловую систему, после чего initrd
размонтируется и освобождается память. Во многих встраиваемых системах
initrd так и остаётся корневой файловой системой. В этой статье
исследуется загрузочный RAM диск для ядра Linux 2.6, включая процесс его
создания и использования в ядре линукса.
Что такое загрузочный RAM диск?
Загрузочный RAM диск (Initrd) это образ корневой файловой системы,
который монтируется до того как настоящая корневая фс будет доступна.
Initrd связан с ядром и загружается как часть ядра в процессе загрузки
системы. Ядро монтирует образ initrd в котором находятся необходимые
модули для монтирования корневой фс и уже дальнейшего перехода в этот
корень как основной.
В initrd содержится минимальный набор директорий и исполняемых файлов
для загрузки модулей, например insmod для загрузки модулей ядра.
В случае настольной системы или сервера, initrd временная файловая
система. Её время жизни коротко и служит лишь связующим звеном к
корневой фс. Во встраиваемых системах нет записываемых устройств
хранения данных, поэтому initrd является постоянной корневой фс. В этой
статье исследуются оба варианта.
Внутреннее устройство initrd
В образе initrd содержится необходимый минимум исполняемых и системных
файлов для осуществления второй стадии загрузки linux. В зависимости от
версии linux которую вы используете, различаются методы создания initrd.
До к Fedora Core 3, initrd создавался с использованием виртуального loop
устройства. Виртуальное устройство loop позволяет монтировать файлы как
блочные устройства и обращаться с ними как будто на них есть реальная
файловая система. У вас в ядре может и не быть драйвера для loop, но его
можно включить в конфигурацию ядра, выбрав **Device Drivers > Block
Devices > Loopback Device Support**. Вы можете изучить работу loop
устройства с помощью этих команд (имя вашего образа initrd может
отличаться):
Листинг 1. Исследование initrd (до FC3)
# mkdir temp ; cd temp
# cp /boot/initrd.img.gz .
# gunzip initrd.img.gz
# mount -t ext -o loop initrd.img /mnt/initrd
# ls -la /mnt/initrd
Теперь вы можете посмотреть содержимое initrd в директории /mnt/initrd.
Заметьте что даже если имя вашего образа initrd не заканчивается .gz,
это все равно сжатый файл и добавив к концу имени .gz вы сможете
воспользоваться командой gunzip, чтобы его распаковать.
Начиная с Fedora Core 3, по умолчанию образ initrd это сжатый cpio
архив. Вместо монтирования файла с использованием loop device, нужно
использовать программу cpio. Чтобы исследовать содержимое cpio архива,
используйте следующую последовательность команд:
Листинг 2. Исследование initrd(FC3 и более поздние версии)
В итоге мы имеем маленькую корневую фс, содержимое которой показано в
листинге 3. Маленький, но необходимый набор приложений присутствует в
каталоге /bin, включая nash (not a shell, интерпретатор скриптов),
insmod для загрузки модулей ядра и lvm (утилита для управления lvm).
Листинг 3. Структура initrd по умолчанию (для FC3)
# ls -la
#
drwxr-xr-x 10 root root 4096 May 7 02:48 .
drwxr-x--- 15 root root 4096 May 7 00:54 ..
drwxr-xr-x 2 root root 4096 May 7 02:48 bin
drwxr-xr-x 2 root root 4096 May 7 02:48 dev
drwxr-xr-x 4 root root 4096 May 7 02:48 etc
-rwxr-xr-x 1 root root 812 May 7 02:48 init
-rw-r--r-- 1 root root 1723392 May 7 02:45 initrd-2.6.14.2.img
drwxr-xr-x 2 root root 4096 May 7 02:48 lib
drwxr-xr-x 2 root root 4096 May 7 02:48 loopfs
drwxr-xr-x 2 root root 4096 May 7 02:48 proc
lrwxrwxrwx 1 root root 3 May 7 02:48 sbin -> bin
drwxr-xr-x 2 root root 4096 May 7 02:48 sys
drwxr-xr-x 2 root root 4096 May 7 02:48 sysroot
#
Интерес в листинге 3 представляет файл init в корне. Это файл, как и в
традиционном процессе загрузки linux, запускается когда образ initrd
распаковывается в память. Мы разберем этот процесс позже в этой статье.
Утилиты для создания образа initrd
Давайте вернемся в начало и формально разбремся как создается образ
initrd. Для традиционных linux систем образ initrd содается в процессе
установки. Огромное количество программ, таких как mkinitrd, могут быть
использованны для создания initrd с необходимыми библиотеками и модулями
для связи с реальной корневой фс. Mkinitrd это по сути обычный shell
скрипт, так что вы можете посмотреть каким образом достигается нужный
нам результат. Есть так же YAIRD (Yet Another Mkinitrd) - программа,
которая позволяет настроить практически любой параметр в initrd.
Команда cpio Используя команду cpio, вы можете
манипулировать cpio файлами. Файл Cpio это по сути простая конкатенция
файлов с заголовками. Формат файла cpio позволяет работать как с ascii
файлами, так и с бинарными. Для совместимости используйте ascii, для
уменьшения размера - бинарную версию.
Создание вручную индивидуального образа initrd
----------------------------------------------
По причине того что на многих встраиваемых системах, основанных на linux
нет жесткого диска, initrd так же является и постоянной фс. Листинг 4
показывает как создавать образ initrd. Я использую стандартный десктоп с
linux'ом, так что вы можете опробовать эти действия не имея под рукой
встраиваемой системы с linux'ом. Не считая компиляции под другую
платформу, концепция создания образа initrd одинакова для встраиваемых
систем и обычных компьютеров (включая сервера).
Листинг 4. Утилита (mkird) для создания индивидуального образа initrd
# Grab the necessary dev files
cp -a /dev/console /mnt/initrd/dev
cp -a /dev/ramdisk /mnt/initrd/dev
cp -a /dev/ram0 /mnt/initrd/dev
cp -a /dev/null /mnt/initrd/dev
cp -a /dev/tty1 /mnt/initrd/dev
cp -a /dev/tty2 /mnt/initrd/dev
# Equate sbin with bin
pushd /mnt/initrd
ln -s bin sbin
popd
# Create the init file
cat >> /mnt/initrd/linuxrc << EOF
#!/bin/ash
echo
echo "Simple initrd is active"
echo
mount -t proc /proc /proc
mount -t sysfs none /sys
/bin/ash --login
EOF
# Grab the necessary dev files
cp -a /dev/console /mnt/initrd/dev
cp -a /dev/ramdisk /mnt/initrd/dev
cp -a /dev/ram0 /mnt/initrd/dev
cp -a /dev/null /mnt/initrd/dev
cp -a /dev/tty1 /mnt/initrd/dev
cp -a /dev/tty2 /mnt/initrd/dev
# Equate sbin with bin
pushd /mnt/initrd
ln -s bin sbin
popd
# Create the init file
cat >> /mnt/initrd/linuxrc << EOF
#!/bin/ash
echo
echo "Simple initrd is active"
echo
mount -t proc /proc /proc
mount -t sysfs none /sys
/bin/ash --login
EOF
Чтобы создать образ initrd, начнем с создания пустого файла, используя
псевдоустройство /dev/zero (просто поток нулей) в качестве входящего
потока в файл ramdisk.img. В результате получим файл размером 4
мегабайта (4000 блоков по 1ому килобайту). Потом, используя команду
mke2fs, создадим в этом файле файловую систему ext2. После того как файл
отформатирован в ext2, смонтируем его в каталог /mnt/initrd как
устройство loop. В точке монтирования у вас теперь есть директория,
которая отражает ext2 файловую систему файла и там вы уже можете
собирать свой образ initrd.
Следующим шагом является создание необходимых подкаталогов: /bin, /sys,
/dev и /proc. Нужно только необходимое, для обеспечения требуемой
функциональности, например не нужно никаких библиотек (это условие верно
когда все исполняемые файлы находящиеся в образе initrd скомпилированны
статически).
Чтобы такая корневая фс предоставляля необходимый функционал используйте
BusyBox. Это приложение является единым образом для многих утилит,
которые обычно используюся в linux системах (такие как ash, awk, sed,
insmod etc.) . Приемущество BusyBox в том что он, включая в себя
функциональность многих необходимых утилит, имеет куда меньший размер.
Это идельный выход для встраиваемых систем. Скопируйте BusyBox в каталог
/bin в корневой файловой системы вашего образа initrd. Создайте
необходимые символические ссылки (на те же ash, awk, sed и т.д.) в
каталоге /bin на BusyBox. BusyBox выясняет какая утилита была запущена и
предоставляет необходимые функции. Небольшое количество ссылок создаётся
в этом каталоге чтобы заработал init скрипт (ссылки эти указывают опять
же на BusyBox).
Следующий шаг - это создание необходимых файлов устройст. Я копирую их
прямо из каталога /dev со своей рабочей системы используя опцию -a (для
cp) чтобы сохранить атрибуты файлов.
Предпоследний шаг - создание файла linuxrc. После того как ядро
монтирует ram диск, оно ищет init скрипт для выполнения. Если файл init
не найден, ядро выполняет файл linuxrc вместо init. В этом файле
выполняются основные операции для установки окружения, например
монтируется файловая система /proc. В дополнении к /proc у меня так же
монтируется файловая система /sys и выводит сообщение в консоль. В конце
запускается ash (клон Bourne shell) чтобы можно было взаимодействовать с
корневой фс. Файлу linuxrc ставится флаг исполняемости (+x) используя
команду chmod.
В итоге мы получаем готовую корневую фс. Образ размонтируется и
сжимается с помощью gzip. Результирующий файл (ramdisk.img.gz)
копируется в каталог /boot для того чтобы можно было загрузить GRUB'ом
или lilo.
Чтобы создать начальный RAM диск, можно просто запустить mkinitrd и он
автоматически соберет образ и скопирует его в каталог /boot
Дистрибутив linux в initrd Был разработан интересный open
source проект, в котором весь дистрибутив linux помещался в образ
initrd, называется он MiniMax. Он занимает 32 мегабайта , включает в
себя BusyBox и uClibc для меньшего размера. Несмотря на маленький
размер, это дистрибутив на основе ядра 2.6 и несет в себе довольно
большое количество полезных утилит.
Альтернатива файловой системе ext2 Ext2 это стандарт
де-факто для linux, но если альтернативы, которые позволяют уменьшить
размер итогового образа initrd. К примеру romfs (файловая система ROM),
cramfs (сжатая файловая система ROM) и squashfs (сильно сжатая файловая
система только для чтения). Если вам нужно что то писать на фс, ext2
вполне для этого подходит. Напоследок есть еще e2compr - это расширения
для драйвера ext2, которое поддерживает сжатие.
Тестирование индивидуального образа initrd
Итак, ваш новый образ initrd лежит в каталоге /boot, следующим шагом
нужно оттестировать его с вашим ядром. Перезагрузите систему и когда
появится приглашение GRUB, нажмите клавишу C, это переведет GRUB в
режим командной строки. Вы можете взаимодествовать с GRUB'ом например
чтобы передать ядру специфические параметры или загрузить свой образ
initrd. Команда kernel определить какое ядро загружать, а команда
initrd выбрать образ initrd. Когда эти параметры определны, наберите
boot и загрузчик загрузит указанные ядро и initrd.
Листинг 5. Ручная загрузка ядра и initrd используя GRUB
GNU GRUB version 0.95 (638K lower / 97216K upper memory)
[ Minimal BASH-like line editing is supported. For the first word, TAB
lists possible command completions. Anywhere else TAB lists the possible
completions of a device/filename. ESC at any time exits.]
После того как ядро запущенно, оно проверяет доступен ли initrd
(подробнее об этом позже) и образ initrd доступе, ядро загружает его в
память и монтирует как корневую фс. Вы можете посмотреть на процесс
загрузки в листинге 6. Когда initrd загружен, становится доступна
оболочка ash. В этом примере я исследую корневую фс и опрашиваю
виртуальную файловую систему /proc. Я так же демонстрирую возможность
писать на файловую создавая файл командой touch. Обратите внимание на то
что первый созданный процесс это linuxrc (обычно init).
Листинг 6. Загрузка ядра linux с простым initrd
...
md: Autodetecting RAID arrays
md: autorun
md: ... autorun DONE.
RAMDISK: Compressed image found at block 0
VFS: Mounted root (ext2 file system).
Freeing unused kernel memory: 208k freed
/ $ ls
bin etc linuxrc proc sys
dev lib lost+found sbin
/ $ cat /proc/1/cmdline
/bin/ash/linuxrc
/ $ cd bin
/bin $ ls
ash cat echo mount sysctl
busybox dmesg ls ps
/bin $ touch zfile
/bin $ ls
ash cat echo mount sysctl
busybox dmesg ls ps zfile
Процесс загрузки с начальным RAM диском
Теперь вы знаете как собрать свой образ initrd, в этой часте астатьи мы
рассмотрим как ядро идентифицирует и монтируется initrd как корневую фс.
Я прошелся через этот процесс останавливаясь на некоторых важных
функциях в цепочке загрузки, объясняя что происходит.
Загрузчик, например GRUB, идентифицирует ядро, которое нужно загрузить и
копирует образ ядра и initrd в память. Вы можете найти описание всех
необходимых функций в каталоге /init в дереве исходных кодов ядра.
После того как ядро и initrd распакованы и скопированны в память,
исполняется ядро. В этом месте происходит много разных инициализационных
процедур, в конечном счете вы оказываетесь в функции init/main.c:init()
(поддиректория/файл:функция). Эта функция как раз и представляет собой
подсистему инициализации. Отсюда идет вызов функции
init/do_mounts.c:prepare_namespaces(), которая подготавливает рабочее
пространство (монтирует файловую систему dev, RAID или md устройства и,
в итоге, сам initrd). Загрузка initrd выполняется вызовом
init/do_mounts_initrd.c:initrd_load().
Функция initrd_load() вызывает init/do_mounts_rd.c:rd_load_image()
которая определяет браз RAM диска, чтобы загрузить его в
init/do_mounts_rd.c:identify_ramdisk_image(). Это функция проверяет
"магическое число" образа чтобы определить какая фс в этом образе:
minux, ext2, romfs,cramfs или формат gzip. Возвраящаясь к функции
initrd_load_image, происходит вызов init/do_mounts_rd:crd_load(). Эта
функция выделяет в памяти место под RAM диск и считает контрольную сумму
(CRC), после этого распаковывает и загружает RAM диск в память. Теперь
ваш образ initrd находится в подходящем для монтирования блочном
устройстве.
Монтирование блочного устройства в качестве корневого раздела начинается
в функции init/do_mounts.c:mount_root(). Создаётся корневой раздел и
происходит вызов init/do_mounts.c:mount_block_root(). Отсюда вызывается
init/do_mounts.c:do_mount_root(), который вызывает
fs/namespace.c:sys_mount(), чтобы уже смонтировать корневую фс и перейти
в неё. Это то место где выводится в консоль знакомое нам по листингу 6
сообщение VFS: Mounted root (ext2 file system).
В конце, вас возвращает в функцию init и происходит вызов
init/main.c:run_init_process. Это происходит в результате вызова execve
чтобы запустился процесс init (в данном случае linuxrc). Linuxrc может
быть как исполняемым файлом, так и скриптом (если для скрипта есть
интерпретатор).
В листинге 7 показана иерархия функций. Не все функции учавствующие в
процессе копирования и монтирования инициализационного RAM диска
показаны здесь, но общее представление об общем процессе здесь дано.
Листинг 7. Иерархия основных функций участвующих в процессе загрузки и
монтирования initrd
Почти как во встраиваемых системах, локальный диск (флоппи или CD-ROM)
не обязательны чтобы загрузить ядро и корневую фс в RAM. Протокол
динамического назначения адресов или просто DHCP может быть использован
для того чтобы определить такие параметры как IP адресс и маску подсети.
Упрощенный протокол передачи данных (TFTP) может быть использован для
передачи образа ядра и образа initrd на локальную машину. После
передачи, ядро может быть загружено, а initrd смонтирован, так как будто
это загрузка с локальной машины.
Уменьшение размера образа initrd
Когда вы создаёте встраиваемую систему и хотите добится наименьшего
размера от образа initrd, если несколько хитростей чтобы это сделать.
Первый совет - используйте BusyBox (описано в статье). BusyBox включает
в себя несколько мегабайт утилит и сжимает их всего до нескольких сотен
килобайт.
В этом примере BusyBox скомпилирован статически, т.е. ему не нужно для
работы никаких библиотек. Однако, еесли вам нужны стандартные библиотеки
языка C (для дополнительных программ), есть нескольно путей решить эту
проблемму не используя массивный glibc. Первая маленькая библиотека
подходящая для наших целей это uClibc, которая является минимизированной
версией стандартной библиотеки C для систем с ограниченным местом.
Другая библиотека, идеальная с точки зрения занимаемого дискового
пространства это dietlib. Не забывайте что для того чтобы ваши программы
работали с урезанными версиями, эти программы нужно перекомпилировать
используя эти библиотеки, потребуется некоторая дополнительная работа,
но оно того стоит.
Итог
Изначально инициализацонный RAM диск был создан для того чтобы связать
ядро и конечную корневую файловую систему, будучи транзитной корневой
фс. Initrd можно так же использовать как непостоянную файловую систему,
смонтрованную как RAM диск для встраиваемых систем.
Дополнения (от переводчика)
Способ создания образа Initrd, описанный в статье, к сожалению не
отвечает современным реалиям. Ramdisk накладывает определенные
ограничения на Initrd. Разработчики решили не мирится с таким положением
дел и перешили к другой концепции создания "связуещего звена" между
ядром и реальной корневой фс. В результате вместо initrd теперь
initramfs. За более подробным объяснением концепции перехода от initrd
к initramfs можно обратится к статье initramfs - новая модель
инициализации.
Некоторые дополнения относительно Debian и создания образа Initramfs
Дистрибутив Debian идёт в ногу со временем и в свежем релизе etch 4.0
уже используется initramfs (в sarge initrd). Для создания образа
initramfs в etch есть замечательный набор утилит initramfs-tools. Для
создания нового образа используется команда mkinitramfs, для обновления
существующего update-initramfs. Конфигурацию оба этих скрипта берут из
дерктории /etc/initramfs-tools.
С помощью этих командой можно посмотреть структуру существющего initramfs:
На счет встраиваемых систем не могу сказать ничего конкретного, кроме
того что ничего не мешает использовать в них initramfs.
Оригинал статьи: http://www-128.ibm.com/developerworks/linux/library/l-initrd.html
Автор M. Tim Jones mtj@mtjones.com
Перевод dkulikovsky crazy.format(gav)gmail.com
1149 Прочтений • [Общее представление о initrd (Initial RAM disk) (linux boot initrd)] [08.05.2012] [Комментариев: 0]