Вопрос или проблема
Я хочу загрузить систему с initramfs, который является фактической финальной файловой системой, а не временным initramfs для загрузки драйверов. К сожалению, Linux накладывает различные (и в моем случае, нежелательные) поведения при использовании initramfs, включая по крайней мере следующие различия:
- devtmpfs не монтируется автоматически, по крайней мере, сначала, но, похоже, монтируется автоматически позже, что я не могу выяснить.
- Вместо запуска
/sbin/init
(или программы init, указанной с помощьюinit=
в командной строке) ядро пытается вызвать/init
.
Я знаю, что можно обойти эти проблемы, добавив некоторые дополнительные файлы в initramfs, но мне бы хотелось, чтобы он вел себя как нормальная корневая файловая система. Есть ли способ достичь этого?
Если мне все же нужно обойти это с помощью скриптов пользовательского пространства в initramfs, я хотя бы хочу понять, что вызывает автоматическое монтирование devtmpfs.
Это возможно, если CONFIG_BLOCK
не определен, поскольку init/do_mounts.c
содержит в mount_root
, который выполняется после того, как ядро не смогло выполнить /init
на initramfs, следующее:
#ifdef CONFIG_BLOCK
{
int err = create_dev("/dev/root", ROOT_DEV);
if (err < 0)
pr_emerg("Не удалось создать /dev/root: %d\n", err);
mount_block_root("/dev/root", root_mountflags);
}
#endif
В этом случае mount_root
проходит успешно, ничего не сделав, и ядро продолжает рассматривать initramfs как правильную корневую файловую систему.
К сожалению, отключение CONFIG_BLOCK
не является практичным для большинства случаев использования. То, что навело меня на мысль, что это должно работать, так это то, что в патче для конкретной платформа разработки, с которой я работаю, условие было заменено на:
#if defined(CONFIG_BLOCK) && !defined(CONFIG_INITRAMFS_SOURCE)
Было бы неплохо добавить поддержку для root=initramfs
, которая заставляет mount_root
возвращаться, не выполняя никаких действий, и это должно быть тривиальным однострочным патчем. У меня нет представления о том, будет ли это приемлемо для upstream.
Ну, это довольно поздно, но у меня есть ответ, который может вам помочь:
Во-первых, вам нужно будет включить /dev/console в ваш initramfs. Это позволит вам получить функциональность sysinit, сообщающую обратно на консоль (выводы из пользовательского пространства снова отобразятся на вашем основном экране). Далее, если вы используете busybox для вашего процесса инициализации, добавьте символическую ссылку на busybox в корне вашей корневой файловой системы под названием init. Проблема в том, что файловый слой ядра Linux изменился несколько лет назад. Изначально вам нужно было иметь /init, чтобы запустить систему. Это считалось уязвимостью и было перемещено в /sbin/init. Позже, если я правильно помню, это стало linuxrc, но, как я думаю, это было полностью удалено.
В моем inittab первые две строки монтируют proc и devtmpfs. Все кажется работает правильно.
Для тех, кто пытается использовать initrd как корневую файловую систему и попал в эту тему, пожалуйста, убедитесь, что /init
существует на initrd, или отрегулируйте это в командных аргументах ядра, используя rdinit=xxx
по мере необходимости.
Ответ или решение
Для того чтобы Linux воспринимал initramfs как финальную корневую файловую систему, необходимо учитывать несколько нюансов, связанных с поведением ядра и конфигурацией системы. Инициализационные file systems (initramfs) традиционно используются для загрузки необходимых модулей и драйверов, а не как основная файловая система. Однако при определённых условиях это поведение можно изменить.
Проблемы с использованием initramfs
-
Отсутствие автоматического монтирования devtmpfs. Это может привести к тому, что устройства не будут доступны до момента, когда devtmpfs будет смонтирован.
-
Запуск файла init. В отличие от ожидаемого поведения, когда запускается
/sbin/init
, ядро пытается выполнить/init
, что может вызвать путаницу.
Решение проблемы
Чтобы заставить Linux работать с initramfs как с окончательной корневой файловой системой, можно использовать следующие подходы:
-
Изменение конфигурации ядра:
- Если у вас есть возможность модифицировать настройки ядра, можно отключить
CONFIG_BLOCK
. Это позволит функцииmount_root
завершаться успешно без необходимости выполнять дополнительные шаги по монтированию корневой файловой системы, что, в свою очередь, позволит обращаться к initramfs в качестве финальной файловой системы. Однако данный подход может быть непрактичным для повседневного использования.
- Если у вас есть возможность модифицировать настройки ядра, можно отключить
-
Требования к содержимому initramfs:
- Включите в initramfs файл
/dev/console
. Это позволит получать сообщения о состоянии и инициализации системы, что крайне важно при отладке. - Убедитесь, что в initramfs присутствует символьная ссылка на
busybox
, ведущее к/init
. Это важно, поскольку линейка файловой системы Linux значительно изменилась, и наличие файла/init
становится обязательным.
- Включите в initramfs файл
-
Использование скриптов пользователей: Если вы решите обойти указанные проблемы с помощью пользовательских скриптов, вы можете создать скрипт инициализации, который будет:
- Монтировать
proc
иdevtmpfs
в самом начале выполнения. - Обеспечить, чтобы файл
/init
существовал в initramfs или использовать параметр командной строкиrdinit=xxx
для указания пути к инициализирующему исполняемому файлу.
- Монтировать
Понимание автозагрузки devtmpfs
Автозагрузка devtmpfs зависит от того, когда и как система будет инициализировать устройства. В современных версиях ядра процесс может активироваться при помощи отдельного модуля инициализации, который отвечает за создание специального файла /dev/root
. Для понимания того, что именно вызывает автоматическое монтирование devtmpfs, рекомендуется просмотреть код ядра, особенно функции, связанные с инициализацией root файловой системы.
Заключение
В заключение, непосредственно изменять поведение Linux для обработки initramfs как корневой файловой системы достаточно сложно, но возможно. Основным подходом является либо модификация настроек ядра, либо создание соответствующей структуры и конфигурации initramfs. Важно помнить о том, что любые изменения следует тестировать на изолированном окружении перед внедрением в рабочие системы, чтобы избежать незапланированных сбоев и проблем с загрузкой.