Зачем мне нужны initramfs?

17

Я обнаружил, что если я выберу jffsили в sdкачестве файловой системы (а не initramfs), размер ядра будет очень маленьким (1,4 МБ по сравнению с initramfs3,4 МБ). Это означает, что initramfsзанимает значительно больше места. Так что если бы я мог, я бы полностью удалил его, и, таким образом, у меня было бы очень маленькое ядро, чего я и хочу.

Основной вопрос, который возникает у меня в голове: «Зачем мне это нужно initramfs? Ядро Linux не может загрузиться без какой-либо начальной файловой системы

Мое конечное приложение будет выполнять только расчеты и связь - без хранения вообще. Поэтому ОС без файловой системы имеет смысл - по крайней мере, для моего приложения.

gpuguy
источник
2
Вы не можете обойтись без initramfs. Можно обойтись без дополнительного файла initramfs, но независимо от того, что вы делаете, ядро ​​содержит свой собственный пустой или нет. Так что я не понимаю вашего вопроса - о каком распространении вы говорите? Как вы строите свое ядро? Можете ли вы предоставить файл ядра .config? Это очень важно. Я подозреваю, что ваш дистрибутив компилирует свои initramfs непосредственно в ядро ​​- и поэтому заполняет остальные пустые initramfs, которые он содержит - но я не могу знать, основываясь на информации, которую вы предоставили.
mikeserv
2
@mikeserv, очевидно, встроенный, но пустой / неиспользуемый initramfs не считается.
psusi
Ну, @psusi с ядром не согласен. И я так непреклонен в этом, потому что не должно быть никакой тайны - просто ... /rootвот и все. Единственное, что он делает по-другому, - это switch_rootто, что даже в том случае, если при определенных загруженных модулях ядра соблюдаются надлежащие меры предосторожности, это можно сделать в любое время. Initramfs - это не что иное, как образ диска - заполнен или нет, он есть. И ты никогда не без этого - ведь это твой корень. Это просто не должно быть загадкой, это то, что я думаю, и мне не нравится вся ненужная путаница вокруг этого.
mikeserv
2
@mikeserv, no, / root - домашний каталог для пользователя root. Rootfs - это /, у которого поверх него монтируется настоящий корень. Вы просто спорите с семантикой. Для целей этого обсуждения отсутствие initramfs означает отсутствие файла на диске, который ваш загрузчик должен загрузить и передать ядру.
psusi
Это правда, я использовал / root только для ясности, но я дам вам это. Но нет, это не семантика, это фундаментальная механика вашего ядра Linux. Это основные вещи. Давайте просто попробуем сделать их правильно.
mikeserv

Ответы:

12

Увеличение размера наличия initramfs происходит не из-за драйвера ramfs (это всего лишь несколько килобайт и все равно нужно для других вещей), а из-за самого initramfs. Initramfs содержит программы, необходимые для сборки и монтирования настоящей корневой файловой системы.

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

Разумеется, ядро ​​должно загружаться с файловой системы: должен быть какой-то способ загрузить любое приложение, которое вы хотите запустить. Если вы не собираетесь ничего запускать, то вы можете оставить машину выключенной.

Если вы не хотите использовать initramfs, просто скажите вашему загрузчику, чтобы он не пропускался. Также, конечно, не включайте один в вывод сборки ядра - как это происходит, если вообще зависит от архитектуры и загрузчика: например, vmlinuxи bzImageне включайте initramfs (они являются сырым и сжатым ядром соответственно ), но uImage(для U-Boot) упаковывает и ядро, и initramfs, если он есть.

(Технически, как отмечает mikeserv , всегда есть initramfs - но по умолчанию это пустой 134-байтовый архив. То, что вы видите и хотите от него избавиться, - это «истинные», непустые initramfs, созданные ваш процесс сборки и содержащие инструменты, которые затем используются для монтирования корневой файловой системы.)

Имейте в виду, initramfs может быть разумным способом создания системы из одного приложения без постоянных данных: поместите все свое приложение в initramfs, загрузите его и сохраните. Это облегчает организацию вашего постоянного хранилища или загрузочного образа (все, что вам нужно - это ядро ​​и initramfs, которые можно объединить). Однако у этого подхода есть свои недостатки: все данные в initramfs будут постоянно храниться в оперативной памяти, и вы не можете легко изменить файлы в образе загрузки, вам нужно перестроить архив.

Жиль "ТАК - прекрати быть злым"
источник
Если вы используете ядро ​​Linux версии 2.6 или новее, у вас есть initramfs. Используете ли вы вторичный образ initramfs, как обычно, другое дело, но initramfs не является обязательным.
mikeserv
2
@mikeserv У тебя есть один, да. Но пустой initramfs - это арахис. Его не нужно использовать (для этого требуется, чтобы в нем было достаточно программ для монтирования реального корня, что немаловажным образом увеличивает размер в типичной встроенной системе).
Жиль "ТАК - перестань быть злым"
Обязательно арахис в любом случае. И я не знаю, когда я сказал иначе! Аскер запрашивал информацию о том, как удалить его как файловую систему - что невозможно.
mikeserv
И да, его нужно использовать - без initramfs нет рута. Когда-либо.
mikeserv
8

Из LFS :

Единственная цель initramfs - монтировать корневую файловую систему. Initramfs - это полный набор каталогов, которые вы найдете в нормальной корневой файловой системе. Он объединен в один архив cpio и сжат с помощью одного из нескольких алгоритмов сжатия.

...

Существует только четыре основных причины иметь initramfs в среде LFS: загрузка rootfs из сети, загрузка его с логического тома LVM, наличие зашифрованных rootfs там, где требуется пароль, или для удобства указания rootfs как ЭТИКЕТКА или UUID. Все остальное обычно означает, что ядро ​​не было правильно настроено.

...

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

Другой источник www.kernel.org

Кроме того, есть много систем Linux, которые любят маршрутизаторы, которые не используют initramfs.


источник
1

Вам нужен initramfs для более сложных установок, таких как загрузка по сети, lvm или raid, поскольку для настройки доступа к корневому файлу требуются утилиты пользовательского режима. Для простого обычного раздела на диске, если у вас есть встроенные в ядро ​​драйверы дисков и вы указываете корневой аргумент по пути к устройству, а не по UUID, вы можете обойтись без initramfs. Конечно, путь к устройству может меняться в зависимости от того, какие подключенные устройства (например, usb) вы подключили, или даже от случайных временных вариаций, поэтому почти все используют uuids и initramfs для надежности.

psusi
источник
Это тоже неверно.
mikeserv
6
@mikeserv, твой комментарий бесполезен. Если вы собираетесь это утверждать, вам нужно объяснить, почему.
psusi
Я сделал, точнее, документацию по ядру, составляющую около 99% моего ответа.
mikeserv
@mikeserv, это правильно. Я использую Gentoo Linux уже много лет без initramfs.
Тим
1

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

С https://www.kernel.org/doc/Documentation/early-userspace/README (полностью внизу, где говорится, что оно не обновлялось с 2004 года.)

В настоящее время ядро ​​имеет 3 способа монтирования корневой файловой системы:

а) все необходимые драйверы устройств и файловых систем, скомпилированные в ядро, без initrd. init / main.c: init () будет вызывать prepare_namespace () для монтирования конечной корневой файловой системы на основе опции root = и необязательного init = для запуска другого двоичного файла init, отличного от указанного в конце init / main.c: init ().

б) некоторые драйверы устройств и файловых систем, собранные в виде модулей и сохраненные в initrd. Initrd должен содержать двоичный файл '/ linuxrc', который должен загружать эти модули драйверов. Также возможно смонтировать конечную корневую файловую систему через linuxrc и использовать системный вызов pivot_root. Initrd монтируется и выполняется с помощью prepare_namespace ().

в) используя initramfs. Вызов метода prepare_namespace () должен быть пропущен. Это означает, что двоичный файл должен выполнять всю работу. Указанный двоичный файл может быть сохранен в initramfs либо путем изменения файла usr / gen_init_cpio.c, либо через новый формат initrd, архив cpio. Он должен называться "/ init". Этот двоичный файл отвечает за все действия, которые будет выполнять prepare_namespace ().

Для обеспечения обратной совместимости двоичный файл / init будет работать только в том случае, если он поступает через архив initramfs cpio. Если это не так, init / main.c: init () запустит prepare_namespace (), чтобы смонтировать финальный корень и выполнить один из предопределенных двоичных файлов инициализации.

Я считаю, что устройства / дистрибутивы, такие как Raspberry Pi и т. Д., Не используют initramfs; в некоторых случаях ядро ​​находится в корневом разделе (смонтирован загрузчиком, имеющим необходимые модули fs.) В других случаях, когда ядро ​​находится, например, в /bootразделе, к initramfs в этом же разделе можно обращаться непосредственно перед монтированием rootfs, как и другие. заявили.

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

thom_nic
источник
0

Я нахожу следующее объяснение более ясным,

initramfsкорневая файловая система, которая встроена в ядро ​​и загружена на ранней стадии процесса загрузки. Это преемник initrd. Он обеспечивает раннее пользовательское пространство, которое может делать то, что ядро ​​не может легко сделать самостоятельно во время процесса загрузки.

Использование initramfs необязательно. По умолчанию ядро ​​инициализирует оборудование с помощью встроенных драйверов, монтирует указанный корневой раздел, загружает систему инициализации установленного дистрибутива Linux. Затем система init загружает дополнительные модули и запускает службы, пока в конечном итоге не позволит вам войти в систему. Это хорошее поведение по умолчанию и достаточно для многих пользователей. initramfs для пользователей с расширенными требованиями; для пользователей, которые должны сделать что-то как можно раньше, даже до монтирования корневого раздела.

Вот несколько примеров того, что вы можете сделать с initramfs:

  • Смонтировать корневой раздел (для зашифрованных, логических и других специальных разделов);
  • Обеспечить минималистичную спасательную оболочку (если что-то пойдет не так);
  • Настроить процесс загрузки (например, распечатать приветственное сообщение, заставку и т. Д.);
  • Загрузка модулей (например, сторонних драйверов);
  • Все, что ядро ​​не может сделать (пока вы можете делать это в пространстве пользователя, например, выполняя команды). Если у вас нет расширенных требований, вам не нужны initramfs.
Суфиян Гори
источник
-1

Неважно, что вы делаете, у вас есть initramfs. Без этого не обойтись - это единственная файловая система, навязанная вам. С kernel.org :

Что такое rootfs?

Rootfsэто особый экземпляр ramfs(или tmpfs, если он включен), который всегда присутствует в системах 2.6. Вы не можете размонтироватьrootfs по той же причине, по которой не можете убить процесс инициализации; вместо того, чтобы иметь специальный код для проверки и обработки пустого списка, ядру меньше и проще просто убедиться, что определенные списки не могут стать пустыми.

Большинство систем просто монтируют другую файловую систему rootfsи игнорируют ее. Количество места, которое занимает пустой экземпляр ramfs, ничтожно мало.

Если * CONFIG_TMPFS * включен, rootfsбудет использоваться tmpfsвместо ramfsпо умолчанию. Чтобы заставить ramfs, добавьте "rootfstype=ramfs"в командную строку ядра.

Что такое initramfs?

Все 2.6 ядра Linux содержат архив в"cpio"форматеgzipped, который извлекается rootfsпри загрузке ядра. После извлечения ядро ​​проверяет,rootfsсодержит ли файл файл"init" , и если это так, оно выполняет его как PID 1. Если он найден, этотinitпроцесс отвечает за доведение системы до конца, включая поиск и подключение реального корневого устройства ( если есть) Еслиrootfsне содержитinitпрограмму послевстроенныйcpioархив извлекается в него, ядро будет проваливаться к старому кодучтобы найти и смонтировать корневой раздел,затем EXEC некоторый вариант/sbin/initиз этого.

Все это отличается от старого initrd в нескольких отношениях:

  • Старый initrd всегда был отдельным файлом, а архив initramfs связан с образом ядра linux. (Каталог linux - * / usr предназначен для создания этого архива во время сборки.)

  • Старый файл initrd представлял собой образ файловой системы в формате gzip (в каком-то формате, например ext2, для которого требовался встроенный в ядро ​​драйвер), в то время как новый архив initramfs представляет собой архив в формате gzip cpio (как и в tar, проще, см. Cpio (1) и Documentation / early-userspace / buffer-format.txt). Код извлечения cpio в ядре не только чрезвычайно мал, но также содержит текст и данные __init, которые могут быть отброшены в процессе загрузки.

  • Программа, запущенная старым initrd (которая называлась / initrd, а не / init), выполнила некоторую настройку и затем вернулась к ядру, в то время как не ожидается, что программа init из initramfs вернется к ядру. (Если / init нужно передать управление, он может смонтировать / с новым корневым устройством и выполнить другую программу init. См. Утилиту switch_root ниже.)

  • При переключении другого корневого устройства initrd будет pivot_root, а затем размонтирует виртуальный диск. Но initramfs - это rootfs: вы не можете ни pivot_root rootfs, ни размонтировать его. Вместо этого удалите все из rootfs, чтобы освободить место (find -xdev / -exec rm '{}' ';'), перемонтируйте rootfs с новым корнем (cd / newmount; mount --move. /; Chroot.), присоедините stdin / stdout / stderr к новой / dev / console и выполните новый init.

Так как это очень придирчивый процесс (и включает удаление команд до того, как вы сможете их запустить), пакет klibc представил вспомогательную программу (utils / run_init.c), которая сделает все это за вас. Большинство других пакетов (таких как busybox) назвали эту команду "switch_root".

Заполнение initramfs:

Процесс сборки ядра 2.6 всегда создает архив initramfs в формате gzipped cpio и связывает его с результирующим двоичным файлом ядра. По умолчанию этот архив пуст (занимает 134 байта на x86).

Параметр конфигурации CONFIG_INITRAMFS_SOURCE (в общих настройках в menuconfig и в usr / Kconfig) можно использовать для указания источника для архива initramfs, который будет автоматически включен в получившийся двоичный файл. Эта опция может указывать на существующий архив cpio gzipped, каталог, содержащий файлы, которые нужно заархивировать, или спецификацию текстового файла, такую ​​как следующий пример:

  dir /dev 755 0 0
  nod /dev/console 644 0 0 c 5 1
  nod /dev/loop0 644 0 0 b 7 0
  dir /bin 755 1000 1000
  slink /bin/sh busybox 777 0 0
  file /bin/busybox initramfs/busybox 755 0 0
  dir /proc 755 0 0
  dir /sys 755 0 0
  dir /mnt 755 0 0
  file /init initramfs/init.sh 755 0 0

Запустите «usr / gen_init_cpio» (после сборки ядра), чтобы получить сообщение об использовании, документирующее указанный выше формат файла.

Одно из преимуществ файла конфигурации заключается в том, что для установки разрешений или создания узлов устройства в новом архиве не требуется root-доступ. (Обратите внимание, что эти две примерные записи «file» ожидают найти файлы с именами «init.sh» и «busybox» в каталоге с именем «initramfs», в каталоге linux-2.6. *. См. Documentation / early-userspace / README для подробнее.)

Ядро не зависит от внешних инструментов cpio. Если вы указываете каталог вместо файла конфигурации, инфраструктура сборки ядра создает файл конфигурации из этого каталога (usr / Makefile вызывает scripts / gen_initramfs_list.sh) и приступает к упаковке этого каталога с помощью файла конфигурации (передавая его usr / gen_init_cpio, который создается из usr / gen_init_cpio.c). Код создания cpio во время сборки ядра полностью автономен, а экстрактор времени загрузки ядра (очевидно) также самодостаточен.

mikeserv
источник
1
Вы можете загрузиться без initramfs. Ваш ответ излагает преимущества initramfs, но это не относится к типичным встроенным системам, и даже на настольных компьютерах или серверах, где рекомендуется initramfs, это не обязательно.
Жиль "ТАК - перестань быть злым"
@ Жиль - нет, ты не можешь. Независимо от того, что вы делаете, у вас есть initramfs. Он скомпилирован в ядро ​​- прямо сейчас, ваше ядро, мое ядро, все наше ядро. Прочитайте документы ядра - весь мой пост был копией-вставкой. Вы не правы. Как вы можете оспорить официальную документацию?
mikeserv
1
Я не оспариваю официальную документацию, я оспариваю выводы, которые вы из нее делаете. Вы читаете документацию, которая объясняет, как использовать initramfs. Нигде не говорится, что initramfs должен использоваться.
Жиль "ТАК - перестань быть злым"
@Gilles Если это не достаточно хорошо: «Процесс сборки ядра 2.6 всегда создает архив initramfs в формате gzipped cpio и связывает его с результирующим двоичным файлом ядра. По умолчанию этот архив пуст (занимает 134 байта на x86) .... " Я могу лучше. Выше был 2 или 3 минуты поиска в сети.
mikeserv
3
Я прочитал документацию. Я делаю это для жизни. Это не вопрос мнения. Всегда есть initramfs, но он не обязательно используется для загрузки. Я не могу найти достойного объяснения структуры ядра для этого случая, вероятно, потому что это классический случай, который, как думают, не требует объяснения. Основная логика заключается, в do_mounts.cчастности prepare_namespace, в том, что saved_root_nameзаполняется root=аргументом командной строки.
Жиль "ТАК - перестань быть злым"