initramfs: временный корень в памяти
initramfs: временный корень в оперативной памяти.
Курица и яйцо при загрузке
К этому моменту цепочка старта уже прошла несколько рук: firmware передаёт управление загрузчику, загрузчик грузит ядро (kernel — центральная программа операционной системы, которая управляет памятью, процессами и железом). Дальше ядру нужно смонтировать настоящий корневой раздел, чтобы запустить первый процесс. И вот тут возникает тупик.
Чтобы прочитать корневой раздел, ядру нужны драйверы: модуль контроллера диска, код для RAID, поддержка LVM (Logical Volume Manager — прослойка, которая собирает физические разделы в гибкие логические тома). А эти модули лежат на том самом разделе, который ещё не смонтирован. Прочитать драйвер нельзя без драйвера.
Собрать всё в ядро статически можно, но тогда один и тот же образ не заведётся на машинах с разным железом. Каждому серверу пришлось бы собирать своё ядро. Так не делают.
Что такое initramfs
initramfs — это сжатый cpio-архив (cpio — старый формат архивации файлов),
который загрузчик кладёт в память рядом с ядром. Ядро распаковывает его в
файловую систему прямо в оперативной памяти. Эта ФС называется rootfs и
живёт на tmpfs (tmpfs — файловая система, которая держит данные только в
RAM), при собранном в ядре CONFIG_TMPFS.
Внутри архива лежит минимальный набор: несколько бинарников, нужные модули
ядра и скрипт init, который знает, как найти и смонтировать настоящий
корень. Заглянуть в содержимое можно, не распаковывая руками:
lsinitramfs /boot/initrd.img-$(uname -r) | head # список файлов внутри архива
Вывод покажет знакомую структуру каталогов:
$ lsinitramfs /boot/initrd.img-6.1.0-18-amd64 | head
.
bin
conf
etc
init
lib
lib/modules/6.1.0-18-amd64/kernel/drivers/md/dm-mod.ko
scripts
usr
Там видно и модуль dm-mod.ko, тот самый драйвер device-mapper для LVM,
без которого корень бы не смонтировался.
Как заглянуть внутрь руками
Формат открытый, распаковать архив можно обычными инструментами. Современный initramfs обычно сжат gzip или zstd:
mkdir /tmp/initrd && cd /tmp/initrd
zcat /boot/initrd.img-$(uname -r) | cpio -idmv # распаковать cpio в текущий каталог
ls # bin etc init lib scripts ...
После распаковки видно, что это полноценное маленькое дерево каталогов со
своим /bin и /lib. Файл init в корне — точка входа, которую запускает
ядро сразу после распаковки.
Переключение на настоящий корень
Скрипт init внутри initramfs грузит нужные модули, находит корневой
раздел (по метке, UUID или пути) и монтирует его. Дальше происходит
переключение: временный корень в памяти уступает место реальному разделу с
диска. За это отвечает switch_root (или его предшественник pivot_root).
# упрощённо, так делает init внутри initramfs
mount /dev/mapper/vg-root /root # смонтировать настоящий корень
exec switch_root /root /sbin/init # сделать его корнем и запустить systemd
После switch_root память, которую занимал initramfs, освобождается, а
управление получает первый настоящий процесс с PID 1 (обычно systemd —
демон, который запускает и следит за остальными демонами по декларативным
unit-файлам). tmpfs с временным корнем к этому моменту уже не нужен.
Механизм появился давно и стал стандартным способом загрузки с ядра
2.5.46. До него применяли старый initrd на основе ram-диска, но initramfs
проще и гибче.
Две частые ловушки
Первая: «initramfs — это и есть корневая ФС с диска». Нет. Это отдельный
временный образ в памяти, живёт секунды и существует только чтобы
смонтировать настоящий корень. Настоящий / лежит на диске и подключается
позже, через switch_root.
Вторая: «его можно удалить, он не нужен». Если стереть файл образа, при следующей загрузке ядро не найдёт драйверы для диска и остановится с паникой ещё до монтирования корня:
$ rm /boot/initrd.img-6.1.0-18-amd64 # так делать не надо
# после ребута:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
Образ пересобирается из установленных модулей командой update-initramfs -u
(Debian/Ubuntu) или dracut (Fedora/RHEL) при обновлении ядра. Руками его
обычно не трогают.
Что важно запомнить
initramfs — сжатый cpio-архив, который ядро распаковывает в rootfs на tmpfs в оперативной памяти.
Он решает проблему курицы и яйца: держит драйверы (диск, LVM), нужные чтобы смонтировать настоящий корень.
lsinitramfs показывает содержимое, zcat ... | cpio -idmv распаковывает
руками.
После монтирования реального корня ядро делает switch_root и запускает
PID 1. Механизм стандартен с ядра 2.5.46.
Это не корень с диска и удалять его нельзя: без него будет kernel panic на монтировании корня.
В следующем уроке — что делает первый процесс: systemd, unit-файлы и параллельный запуск сервисов.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс