initrd img что это

Исследуем процесс загрузки Linux

(C) В.А.Костромин, 2007
(версия файла от 5.10.2007 г.)

Этап 3: Загрузчик 2 этапа операционной системы

3.2. Файл /boot/initrd и его назначение

Как было сказано в предыдущем разделе, в процессе начальной загрузки вначале монтируется временный виртуальный диск, содержащий корневую файловую систему (очевидно, тоже временную), с помощью которой осуществляется запуск на выполнение ядра операционной системы. Образ этой корневой системы хранится на загрузочном устройстве в каталоге /boot и обычно носит имя initrd-2.x.yy-zzzz (точное наименование файла смотрите в вашей системе, далее он будет именоваться просто initrd). Загрузчик переносит образ корневой файловой системы из файла initrd в оперативную пямять одновременно с образом ядра, ядро преобразует initrd в «нормальный» RAM диск, монтирует временную корневую файловую систему, извлекает из нее нужные драйверы и другие служебные файлы, с помощью которых инициализирует все необходимые устройства. После этого происходит перемонтирование корневой файловой системы, временная ФС заменяется на постоянную, размещающуюся уже на долговременном носителе и процесс загрузки системы продолжается.

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

3.2.1. Внутреннее устройство initrd

Как сказано в статье [10] в дистрибутиве Fedora Core 3 (и его предшественниках) файл initrd создавался с использованием виртуального loop-устройства. В этом случае сделать содержимое файла initrd доступным для просмотра можно с помощью следующих команд (напомню, что имя вашего образа initrd может отличаться):

/tmp вы найдете каталоговую структуру, аналогичную структуре каталогов обычной Linux-системы. В ней вы обнаружите обычные для корневого каталога подкаталоги, а также файл linuxrc. Могут там оказаться и другие файлы, например, файл bootsplash (судя по названию он содержит картинку, которая отображается при запуске).

Познакомившись с внутренним содержанием файла initrd можно вернуться к рассмотрению его роли в процессе загрузки.

3.2.2. Загрузка системы в случае использования initrd (ядра версий 2.4.х)

Приводимое ниже описание последовательности операций на этапе загрузки я позаимствовал из [11,12].

2. Ядро содержит в себе небольшую несжатую часть, которая вначале разархивирует само ядро. Видимо как раз на этом этапе на экране монитора отображается сообщение «Uncompressing Linux. Ok, booting the kernel.»

3. Ядро инициализирует устройства, создает файловую систему устройств /dev, разархивирует initrd и копирует его содержимое на устройство /dev/ram0, а затем освобождает память, занятую initrd.

4. Ядро монтирует устройство /dev/ram0 для чтения и записи в качестве начальной корневой файловой системы.

5. Если в начальной корневой файловой системе находится исполняемый файл /linuxrc, он исполняется с uid 0. Этот файл должен иметь разрешения на исполнение, он может быть как обычным исполняемым файлом, так и просто скриптом оболочки, но в последнем случае должен быть и интерпретатор скриптов.

6. Cкрипт /linuxrc монтирует нормальную корневую файловую систему.

7. Корневая файловая система помещается в корневую директорию. Смена корневого устройства выполняется системным вызовом pivot_root, который также доступен через утилиту pivot_root (см. pivot_root(8); pivot_root распространяется в составе util-linux версии не ниже 2.10h ). Смена корневой директории не включает её демонтирование. Следовательно, при выполнении данной процедуры можно сохранить процессы, запущенные с файловой системы initrd.

8. Если нормальная корневая файловая система имеет каталог /initrd, то устройство /dev/ram0 перемещается из / в /initrd. Иначе, если каталог /initrd не существует, устройство /dev/ram0 размонтируется.

9. На нормальной корневой файловой системе следует обычная процедура загрузки (например, вызов /sbin/init).

10. Теперь можно демонтировать /dev/ram0 и освободить память, занятую RAM диском.

Во-первых, виртуальный диск, как и все блочные устройства, требует драйвер файловой системы для интерпретации данных во время выполнения. Этот драйвер приходилось включать в ядро.

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

В третьих, в Linux осуществляется кэширование всех файлов и записей каталогов, прочитанных или записанных на блочное устройство. Виртуальный диск тоже кешируется, как и обычные диски, то есть часть данных будет храниться не только на RAM диске, но и в страничном кэше «page cache» (для файловых данных) и в кэше для записей каталогов «dentry cache», что еще больше снижает эффективность использования памяти.

Формат initramfs используется по умолчанию для всех ядер, начиная с версии 2.6.15.

В каталоге /boot такая файловая система хранится, по-прежнему, в файле в виде сжатого cpio-архива. Только имя включаемого в этот архив скрипта изменилось с linuxrc на init. Например, в системе ASP Linux 11 после разархивирования файла initrd-2.6.14-1.1653.1asp.img по приведенному в листинге 3 алгоритму я увидел скрипт init и следующую структуру каталогов:

Листинг 4. Содержимое файла init в дистрибутиве ASP Linux версии 11. Обратите внимание на первую строку этого файла: это скрипт для оболочки nash, которая является сильно урезанной версией командного процессора и тоже включена в состав initramfs. Другие, более мощные оболочки на этом этапе еще недоступны.

Как видно из листинга 4, скрипт init монтирует файловые системы /sys и /dev, инициализирует несколько устройств, загружает модули из подкаталога /lib и монтирует корневую файловую систему. Сколько я ни вглядывался в экран при перезагрузках системы, я не увидел сообщений, которые вроде бы должны выдаваться командами echo, включенными в этот скрипт.

Образ виртуальной файловой системы initramfs хранится на диске по-прежнему в файле /boot/initrd-version и создается такой файл как и ранее командой mkinitrd. Прочитать о том, как создать такой файл, можно в статье [10]. Перечень модулей (иначе говоря, драйверов), которые будут включены в эту файловую систему, приведен в переменой INITRD_MODULES в файле /etc/sysconfig/kernel. Если вам требуется включить в /boot/initrd-version какие-то дополнительные модули (например, в случае изменения состава оборудования), вы можете скорректировать соответствующим образом список модулей в файле /etc/sysconfig/kernel, после чего заново создать файл /boot/initrd-version.

Источник

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 это сжатый cpio архив. Вместо монтирования файла с использованием loop device, нужно использовать программу cpio. Чтобы исследовать содержимое cpio архива, используйте следующую последовательность команд:

Читайте также:  пряжа на детский плед какую выбрать

Листинг 2. Исследование initrd (FC3 и более поздние версии)

Интерес в листинге 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

# Ramdisk Constants
RDSIZE=4000
BLKSIZE=1024

# Create an empty ramdisk image
dd if=/dev/zero of=/tmp/ramdisk.img bs=$BLKSIZE count=$RDSIZE

# Populate the filesystem (subdirectories)
mkdir /mnt/initrd/bin
mkdir /mnt/initrd/sys
mkdir /mnt/initrd/dev
mkdir /mnt/initrd/proc

# Create the init file
cat >> /mnt/initrd/linuxrc kernel /bzImage-2.6.1
[Linux-bzImage, setup=0x1400, size=0x29672e]

grub> initrd /ramdisk.img.gz
[Linux-initrd @ 0x5f2a000, 0xb5108 bytes]

Uncompressing Linux. OK, booting the kernel.

После того как ядро запущенно, оно проверяет доступен ли initrd
(подробнее об этом позже) и образ initrd доступе, ядро загружает его в
память и монтирует как корневую фс. Вы можете посмотреть на процесс
загрузки в листинге 6. Когда initrd загружен, становится доступна
оболочка ash. В этом примере я исследую корневую фс и опрашиваю
виртуальную файловую систему /proc. Я так же демонстрирую возможность
писать на файловую создавая файл командой touch. Обратите внимание на то
что первый созданный процесс это linuxrc (обычно init).

Листинг 6. Загрузка ядра linux с простым initrd

Процесс загрузки с начальным 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

init/main.c:init
init/do_mounts.c:prepare_namespace
init/do_mounts_initrd.c:initrd_load
init/do_mounts_rd.c:rd_load_image
init/do_mounts_rd.c:identify_ramdisk_image
init/do_mounts_rd.c:crd_load
lib/inflate.c:gunzip
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
init/main.c:run_init_process
execve

Загрузка бездисковых систем

Почти как во встраиваемых системах, локальный диск (флоппи или CD-ROM)
не обязательны чтобы загрузить ядро и корневую фс в RAM. Протокол
динамического назначения адресов или просто DHCP может быть использован
для того чтобы определить такие параметры как IP адресс и маску подсети.
Упрощенный протокол передачи данных (TFTP) может быть использован для
передачи образа ядра и образа initrd на локальную машину. После
передачи, ядро может быть загружено, а initrd смонтирован, так как будто
это загрузка с локальной машины.

Уменьшение размера образа initrd

В этом примере BusyBox скомпилирован статически, т.е. ему не нужно для
работы никаких библиотек. Однако, еесли вам нужны стандартные библиотеки
языка C (для дополнительных программ), есть нескольно путей решить эту
проблемму не используя массивный glibc. Первая маленькая библиотека
подходящая для наших целей это uClibc, которая является минимизированной
версией стандартной библиотеки C для систем с ограниченным местом.
Другая библиотека, идеальная с точки зрения занимаемого дискового
пространства это dietlib. Не забывайте что для того чтобы ваши программы
работали с урезанными версиями, эти программы нужно перекомпилировать
используя эти библиотеки, потребуется некоторая дополнительная работа,
но оно того стоит.

Источник

Модифицируем процесс загрузки с помощью утилиты make-initrd

Модифицируем процесс загрузки с помощью утилиты make-initrd

Упрощенный процесс загрузки ОС Linux

Загрузка ОС на устройстве с UEFI обычно проходит по следующему сценарию:

Размещение в оперативной памяти EFI загрузчика (например, grub) и передача управления ему;

EFI загрузчик записывает образ ядра в оперативную память и вызывает функцию start_kernel;

Ядро инициализирует себя, монтирует корень файловой системы и запускает процесс init, лежащий на корне (/init, /sbin/init или другой). Этим процессом может быть systemd, System V и другие;

Процесс init запускает сервисы и уже подготавливает систему для работы с пользователем.

Такая схема является вполне работоспособной. Но что, если мы хотим усложнить сценарий загрузки? Например, загрузиться с зашифрованного раздела или сетевого диска или, элементарно, проверить файловую систему перед загрузкой. На помощь приходит initramfs!

Что такое initramfs?

Initramfs (Initial ram file system) – образ файловой системы, загружаемый в оперативную память вместе с ядром. Основные задачи этого образа: монтирование реального корня файловой системы и запуск процесса init лежащего на нем.

Многие современные дистрибутивы Linux используют initramfs образы для загрузки системы. Вы можете убедиться в этом сами, найдя файл /boot/* в своем любимом дистрибутиве.

Возможные сценарии использования initramfs

Внутри initramfs образа могут реализовываться разнообразные сценарии загрузки ОС. Все они ограничены лишь возможностями Linux, характеристиками устройства и вашей фантазией.

Читайте также:  что делать если вода в бассейне зеленеет как очистить

Достаточно популярными и широко используемыми сценариями являются:

Вывод приветственной картинки на экран;

Проверка целостности корневой файловой системы;

Загрузка с нестандартных файловых систем;

К экзотическим можно отнести:

Загрузку с образа корня, лежащего в интернете;

Загрузку с зашифрованного раздела;

Загрузку другой ОС с помощью системного вызова kexec.

Утилиты для создания initramfs образов

Разные дистрибутивы используют разные утилиты для создания initrd образов. Debian обычно используют для этого initramfs-tools, Red Hat – Dracut. Но в этой статье я хочу представить другую, менее известную утилиту – make-initrd.

Почему make-initrd?

make-initrd – утилита для создания initramfs образов, разрабатываемая нашим соотечественником Алексеем Гладковым. Сейчас она используется как основной сборщик initramfs в дистрибутиве ALT Linux.

Этот проект обладает рядом преимуществ:

Имеет модульную структуру. Разные логические части образа создаются разными модулями, именуемыми Features (фичами). Например, есть фича luks, отвечающая за внедрение сценария загрузки с зашифрованных разделов LUKS.

Создаваемые initramfs образы имеют простое внутреннее устройство.

Удобен для использования конечным пользователем. Многие части конфигурации определяются автоматически. Это достигается за счет отдельного модуля guess.

Утилита показала свою работоспособность на множестве различных дистрибутивов. Нам лично удавалось собрать и использовать эту утилиту на Ubuntu, Fedora, ALT Linux, Red OS, Astra Linux.

Генерируемые initramfs образы имеют относительно небольшой размер, а их сборка происходит достаточно быстро Для сравнения: initramfs-tools на моей машине генерирует образы размером 51Мб за 24 секунды. Образы же make-initrd весят всего 5Мб и создаются 10 секунд!

Проект продолжает активно развиваться. Со временем появляются новые фичи, улучшается архитектура утилиты и архитектура initramfs образов. Разработчик идет на контакт и всегда рад вашим патчам и предложениям:)

К сожалению, у make-initrd есть и недостатки:

Проект тестируется лишь на Fedora, Ubuntu и Alt Linux. И, хотя нам удавалось использовать его на других дистрибутивах, нет гарантии, что все будет работать гладко и везде.

Устройство initramfs образов, генерируемых make-initrd

В этом разделе описаны основные сведения по архитектуре образов, генерируемых make-initrd.

Сервисы

Создаваемые образы имеют сервисно-ориентированную архитектуру. При передаче управления программе /init порождается дерево сервисов, которые в дальнейшем взаимодействуют между собой. Последовательность их запуска и завершения определяется в процессе сборки образа и настраивается с помощью конфигурационных файлов LSB.

В системе есть несколько основных сервисов, на которых базируется основная логика работы:

udevdобработчик событий ядра об изменении состояния устройств. При изменении состояния любого устройства он параллельно запускает фильтры (скрипты), добавляющие пользовательские события в очередь. Этот демон используется во многих дистрибутивах Linux.

ueventdобработчик пользовательских событий. Этот демон запускает обработчики пользовательских событий. События внутри одной очереди обрабатываются последовательно, а сами очереди – параллельно.

polldдемон, ожидающий выполнения условий загрузки системы. Все, что он делает – один раз в заданное время проверяет условия запуска системы. Если они удовлетворены, запускается некоторый экшен. Скрипты проверки условий и экшена зависят от метода загрузки. Тем не менее, зачастую, их задача – проверить, что корень найден и переключить runlevel на второй уровень.

Runlevel

Runlevel определяет уровень запуска системы. Эти уровни отличаются от тех, что стандартно используются в Linux. В make-initrd номер уровня зависит от состояния загрузки системы. А от номера уровня, в свою очередь, зависит то, какие сервисы будут активны в текущий момент. В make-initrd предусмотрено всего 3 уровня:

Уровень 3 – означает, что реальный корень системы еще не примонтирован. На этом уровне происходит запуск и работа большинства сервисов.

Уровень 2 – означает, что реальный корень системы уже примонтирован. На этом происходит завершение большинства сервисов.

Уровень 9 – специальный уровень, на котором происходит подмена корня системы на реальный и запуск /sbin/init на нем.

Разберем пример загрузки с жесткого диска.

Последовательно запускаются различные сервисы, среди которых будут udevd, ueventd и polld;

После обнаружения устройства жесткого диска ядро сгенерирует соответствующее событие для демона udevd;

udevd просмотрит список своих правил. При нахождении правила на добавление блочного устройства запустится соответствующий обработчик (в make-initrd они называются фильтрами);

В какой-то момент ueventd запустит обработчик этого пользовательского события. Обработчик примонтирует жесткий диск;

Демон polld в очередной раз запустит скрипт проверки наличия корня. После его обнаружения запустится экшен, переключающий runlevel на второй уровень;

После переключения runlevel произойдет отключение большинства сервисов. Далее запустится сервис runinit, который установит runlevel на девятый уровень;

Процесс init произведет подмену корня и запустит /sbin/init ;

Устройство файловой системы initramfs образов

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

/init – программа, которой передается управление после инициализации ядра;

/etc/ – директория конфигураций;

/etc/rc.d/init.d/ – директория LSB конфигураций сервисов;

/etc/udev/rules.d/ – директория правил udevd;

/etc/initrd/method – файл содержащий текущий метод загрузки;

/etc/initrd/cmdline.d/ – директория описаний аргументов ядра;

/lib/uevent/filters/ – директория фильтров uevent событий;

/lib/uevent/handler/ – директория обработчиков uevent событий;

/lib/initrd/boot/method/ – директория скриптов методов загрузки;

/lib/initrd/boot/method/*/check – скрипт проверки условии активации метода загрузки;

/lib/initrd/boot/method/*/action – скрипт активации метода загрузки;

/lib/initrd/boot/scripts/ – директория подскриптов проверки условий метода загрузки;

/.initrd/ – директория, которую могут использовать сервисы и программы для внутренней работы;

/tmp/ – директория временных файлов.

Устройство генератора initramfs образов

process-config – Считывание конфигурационного файла. Во время ее выполнения происходит последовательный запуск целей guess и genimage;

guess – Угадывание конфигурационного файла;

create – Наполнение корня initramfs образа;

pack – Сортировка сервисов и упаковка initramfs образа в cpio архив. Зависит от create;

install – Установка образа в загрузочную директорию. Зависит от pack;

genimage – Вывод информационного сообщения о сборке образа. Зависит от install.

Процесс выполнения этих целей можно разбить на два больших этапа:

1. Угадывание дополнения к конфигурации (цель guess);

2. Сборка образа (цели create – genimage)

Этап угадывания конфигурации

Неправильное задание конфигурации грозит тем, что initramfs образ может оказаться излишне «тяжелым», а загрузка ОС будет происходить медленнее или не происходить вовсе. Например, если вы активировали фичу network, но не используете сеть в процессе загрузки, это грозит вам лишними секундами на настройку сетевых интерфейсов.

Именно для решения этих проблем в make-initrd был добавлен модуль guess. Он помогает оптимально сгенерировать или дополнить существующую конфигурацию, основываясь на окружении компьютера.

Guess использует разные модули для определения разных сфер образа. Например:

device – определяет модули ядра устройств;

keyboard – определяет модули ядра для работы с клавиатурой;

net – определяет модули ядра сетевых устройств;

root – определяет какие разделы нужно примонтировать, а также модули ядра для работы с ними;

smart-card – определяет конфигурацию фичи smart-card;

common – простой универсальный модуль, который может быть использован внутри фич.

Этот список не является исчерпывающим: описание остальных модулей можно посмотреть в README.md файлах модулей guess.

Этап сборки initramfs образа

Во время выполнения цели create создается временная директория, в которой заполняется корень initramfs образа. Корень заполняется в соответствии с переданной конфигурацией. Туда кладется все необходимое: приложения, библиотеки, файлы конфигурации и т.д. Но это еще не все: на последующих шагах корень еще будет дополняться.

Этап сборки образа может сколь угодно расширяться с помощью фич. Например, если активирована фича compress, то cpio архив будет дополнительно сжат с помощью одного из методов: gzip, lzma, bzip2 и т.п.

Фича – это независимый модуль сборщика initramfs образов. Фичи могут воздействовать практически на любой этап сборки образа. Например:

фича compress позволяет сжимать итоговый образ;

фича luks добавляет в initramfs утилиты и модули для работы с luks;

фича clean – очищает после себя рабочую директорию.

Структура проекта make-initrd

Выгрузим проект make-initrd из репозитория и посмотрим на его содержимое

Проект make-initrd очень хорошо структурирован. Давайте опишем, за что отвечают различные файлы и директории в проекте:

Читайте также:  livgardet sabaton о чем песня

data/ – постоянная часть корня initramfs образа. Файлы, находящиеся в ней, будут присутствовать внутри почти всех образов;

datasrc/ – исходники утилит, устанавливаемые внутрь образа;

mk/config.mk – Makefile c постоянной частью конфигурации make-initrd (переменные путей и т.п.);

mk/functions.mk – Makefile с вспомогательными функциями make;

mk/make-initrd.mk – основной Makefile описывающий правила сборки initramfs образа;

tools/ – внутренние утилиты make-initrd;

utils/ – исходники внешних утилит make-initrd;

guess/ – директория guess модулей;

guess/*/config.mk – Makefile с описанием конфигурации guess модуля (переменные модуля, правила его активации). Он подключается вне зависимости от того, активен ли guess модуль или нет;

guess/*/rules.mk – Makefile с описанием правил отработки guess модуля. Он подключается, только если guess модуль активен;

features/ – директория фич;

features/*/data/ – часть корня initramfs образа, предоставляемая фичей;

features/*/datasrc/ – исходники утилит фичи, устанавливаемые внутрь initramfs;

features/*/guess/ – подскрипты модулей guess;

features/*/bin/ – вспомогательный утилиты сборки initramfs образа;

features/*/config.mk – Makefile с конфигурацией фичи (описание зависимых фич, переменных и т.п.). Он подключается вне зависимости от того, активна ли фича или нет;

features/*/rules.mk – Makefile с правилами сборки фичи. Он подключается только в случае, если фича активна.

Установка make-initrd

Сборка initramfs и запуск на реальной машине

ПРЕДУПРЕЖДЕНИЕ Перед генерацией initramfs образа обязательно сделайте backup.

Если система перестанет загружаться, откройте раздел с /boot на другой системе (например, через загрузочную флешку) и верните backup на место. Если вы не сделали backup, попробуйте загрузиться с помощью другого ядра. Это может сработать, так как по-умолчанию make-initrd собирает initramfs только для текущего ядра.

Перезапустим систему и попробуем загрузиться c ядра, для которого мы сгенерировали initramfs образ.

Добавление собственной фичи

Чтобы лучше разобраться с тем, как устроены фичи, давайте напишем свою – hello-usb.

Фича Hello USB

Примечание Исходный код фичи hello-usb можно взять здесь.

Напишем фичу hello-usb, добавляющую в initramfs функционал вывода сообщения “Hello USB!” при нахождении USB-устройства. Также добавим возможность указывать имя производителя устройства, для которого выводится сообщение.

Внутренняя логика работы нашей фичи, следующая:

Контроль добавления нового USB-устройства осуществляется с помощью udev правила /etc/udev/rules.d/99-hello-usb.rules : при добавлении любого USB-устройства вызывается фильтр /lib/uevent/filter/hello-usb

Внутри фильтра создается uevent событие hello-usb

Дерево файлов фичи следующее:

config.mk содержит описание фичи:

Через функцию feature-requires можно указывать зависимые фичи. Мы хотели получить модули ядра и udev-правила для работы с USB-устройствами, поэтому добавили в зависимости фичу usb.

rules.mk содержит правила сборки фичи:

feature/hello-usb/etc/initrd/cmdline.d/hello-usb – регистрирует опцию ядра usb-vendor:

feature/hello-usb/etc/udev/rules.d/99-hello-usb.rules – udev правило, запускающее фильтр. Число в начале имени нужно для задания порядка его обработки. В нашем случае было важно, чтобы правило hello-usb отработало позже, чем 60-fido-id (т.к. оно выставляет тег security-device ). Поэтому мы выставили любое число больше 60 – это 99.

Подробнее о udev правилах можно прочитать здесь.

Обратите внимание на простоту этого скрипта. Это связано с тем, что udev может запустить несколько таких скриптов одновременно, а это может привести к состоянию гонки. Именно поэтому логика большинства фильтров крайне проста – передать событие uevent, который обработает его последовательно.

feature/hello-usb/lib/uevent/handlers/060-hello-usb – обработчик события hello-usb. Uevent передает управление обработчикам в соотвествии с их номером. В нашем случае порядок обработки нашего события не важен, и мы выставили случайный номер – 60.

Соберем make-initrd с добавленной фичей:

Настройка и генерация initrd образа

Обычно файл с конфигурацией выглядит следующим образом:

Здесь написано, что вся конфигурация будет определена автоматически. Увидеть «угаданную» конфигурацию можно с помощью команды:

Вы можете попросить make-initrd запускать только определенные guess модули. Например, можно попросить «угадывать» только модули ядра и фичи необходимые для монтирования корня и работы с клавиатурой:

Попробуем теперь собрать intird образ вместе с фичей hello-usb. Подправим конфигурацию

И запустим сборку образа:

Перейдем к проверке нашего образа на виртуальной машине.

Запуск в qemu

Проверку образа будем производить с помощью qemu. Установим необходимые пакеты:

В процессе работы мы планируем пробрасывать USB-устройство на виртуальную машину. Чтобы это сделать, необходимо узнать его адрес на USB-шине:

Мы хотим пробросить устройство, имеющее класс Mass Storage (флешку). В нашем случае оно находится на первой шине и втором порту.

Перейдем к запуску:

После запуска системы сначала отобразится вывод ядра, а затем вывод самого initrd. Если вы все сделали правильно, в какой-то момент увидите вывод обработчика событий hello-usb:

На этом, увы, ваша система зависнет:) Это связано с тем, что initramfs будет продолжать искать устройство с корнем, но оно не проброшено в qemu. К счастью, есть возможность экстренно перейти в rescue консоль: для этого надо нажать клавиши ** + **.

В ней можно изучить окружение initramfs образа:

* Убедитесь, что файловая структура, описанная ранее, соответствует действительности;

* Изучите список активных процессов;

* Посмотрите логи в /var/log/ ;

* Посмотрите содержимое других файлов.

Вы всегда можете запустить rescue консоль, если имеются какие-либо проблемы при запуске. В ней возможно:

Изучить логи сервисов;

Примонтировать корень вручную и запуститься с него;

Запустить отладчик (если добавлена фича debug-tools).

Передача аргументов ядра

Запустим qemu с аргументом ядра usb-vendor

Заметьте, если указать другое имя производителя, то в лог может ничего не вывестись.

Популярные опции ядра, которые поддерживает initramfs можно посмотреть здесь

Проверка на реальной машине

После того, как вы убедились, что initramfs образ работает в qemu, можно проверить его на реальной машине. Но здесь могут возникнуть некоторые нюансы.

Мы покажем, как это сделать, на примере GRUB.

Настройка аргументов ядра в GRUB

Откроем файл /etc/default/grub. Его содержимое выглядит примерно следующим образом:

Подробнее об опциях grub можно прочитать здесь

Для генерации конфигурации второго уровня выполним команду:

Разбор полученной конфигурации является уже более сложной задачей и выходит за рамки этой статьи. Тем не менее посмотреть на файл /boot/grub/grub.cfg все равно будет полезно:) Подробную информацию о его конфигурации grub можно найти здесь.

Добавим в аргументы ядра, параметр usb-vendor. Для этого зададим в файле /etc/default/grub переменную GRUB_CMDLINE_LINUX_DEFAULT :

И снова обновим конфигурацию:

Перезапустите систему и посмотрите на результат.

Вывод

Естественно, фича hello-usb не раскрывает всю мощь использования make-initrd. Если вы хотите рассмотреть более живые примеры фич, посмотрите исходники фич:

sshfsroot. – фича для загрузки с сетевых дисков по протоколу ssh;

luks – фича для загрузки с зашифрованных разделов;

raid – фича для загрузки с raid разделов.

В первые две, кстати, мы недавно добавили возможность для аутентификации по смарт-карте.

Обратите внимание насколько архитектура этих фичей совпадает с той, что мы реализовывали в hello-usb. Такая структурированность упрощает процесс разработки, и вы можете опираться на нее.

Make-initrd также удобен и для конечного использования. Такая крупная ОС, как ALT Linux, использует его в своих дистрибутивах в качестве основного генератора initramfs образов, в частности на таких продуктах, как “Альт Рабочая станция” и “Альт Сервер”. Это ли не показывает его широкую направленность?

На десктопных платформах вы можете добиться желаемого с помощью пары строк в конфигурационном файле, а порой полностью автоматически. Хотите добавить загрузку c сетевого раздела, используя sshfs? Просто напишите FEATURE += sshfsroot в файле конфигурации, а в опциях ядра укажите адрес сервера. Хотите добавить загрузку с RAID или LVM разделов? Ничего делать не надо! Если ваш корень лежит на таком разделе, make-initrd автоматически подберет правильную конфигурацию.

На серверных решениях вы можете добиться быстрой загрузки за счет высокой конфигурируемости образов. Вы всегда можете отключить любые ненужные вам фичи, тормозящие загрузку вашей системы. За счет обилия имеющегося функционала можно реализовать загрузку практически любой сложности. А если какого-то функционала будет не хавать, можно быстро реализовать его самостоятельно.

Источник

Сказочный портал