Как Linux загружает образ 'initrd'?

13

Я пытался понять процесс загрузки, но есть только одна вещь, которая идет мне в голову ...

Как только ядро ​​Linux будет загружено и смонтирована корневая файловая система (/), программы могут быть запущены, а дополнительные модули ядра могут быть интегрированы для обеспечения дополнительных функций. Чтобы смонтировать корневую файловую систему, должны быть выполнены определенные условия. Ядру нужны соответствующие драйверы для доступа к устройству, на котором расположена корневая файловая система (особенно драйверы SCSI). Ядро также должно содержать код, необходимый для чтения файловой системы (ext2, reiserfs, romfs и т. Д.). Также возможно, что корневая файловая система уже зашифрована. В этом случае требуется пароль для монтирования файловой системы.

Начальный виртуальный диск (также называемый initdisk или initrd) решает проблемы, описанные выше. Ядро Linux предоставляет возможность загружать небольшую файловую систему на диск RAM и запускать на ней программы до монтирования действительной корневой файловой системы. Загрузка initrd выполняется загрузчиком (GRUB, LILO и т. Д.). Загрузчикам нужны только процедуры BIOS для загрузки данных с загрузочного носителя. Если загрузчик может загрузить ядро, он также может загрузить начальный виртуальный диск. Специальные драйверы не требуются.

Если / boot не является другим разделом, но присутствует в разделе /, то не должен ли загрузчик требовать драйверов SCSI для доступа к образу 'initrd' и образу ядра? Если вы можете получить прямой доступ к изображениям, то зачем нам нужны драйверы SCSI?

rpthms
источник

Ответы:

20

Nighpher, я постараюсь ответить на ваш вопрос, но для более полного описания процесса загрузки, попробуйте статью IBM .

Хорошо, я предполагаю, что вы используете GRUB или GRUB2 в качестве загрузчика для объяснения. Прежде всего, когда BIOS обращается к вашему диску для загрузки загрузчика, он использует встроенные подпрограммы для доступа к диску, которые хранятся в знаменитом 13-часовом прерывании. Загрузчик (и ядро ​​на этапе установки) используют эти подпрограммы при доступе к диску. Обратите внимание, что BIOS работает в режиме реального режима (16 бит) процессора, поэтому он не может адресовать более 2 ^ 20 байт оперативной памяти (2 ^ 20, а не 2 ^ 16), поскольку каждый адрес в реальном режиме состоит из сегмента_адреса * 16 + смещение где адрес сегмента и смещение 16-битные, см. http://en.wikipedia.org/wiki/X86_memory_segmentation ). Таким образом, эти подпрограммы не могут получить доступ к более чем 1 МБ ОЗУ, что является строгим ограничением и серьезным неудобством.

BIOS загружает код загрузчика прямо из MBR - первые 512 байт вашего диска и выполняет его. Если вы используете GRUB, этот код относится к этапу GRUB 1. Этот код загружает этап 1.5 GRUB, который находится либо в первых 32 КБ дискового пространства, называемых областью совместимости DOS, либо с фиксированного адреса файловой системы. Для этого не нужно понимать файловую систему, потому что даже этап 1.5 находится в файловой системе, это «сырой» код, который можно напрямую загрузить в ОЗУ и выполнить: http://www.pixelbeat.org/ документы / диск / . Загрузка stage1.5 с диска в RAM использует процедуры доступа к диску BIOS.

введите описание изображения здесь

Stage1.5 содержит утилиты файловой системы, так что он может читать stage2 из файловой системы (ну, он по-прежнему использует BIOS 13h для чтения с диска в RAM, но теперь он может расшифровать информацию файловой системы об инодах и т. Д. И получить необработанный код из диск). Старые BIOS могут быть не в состоянии получить доступ ко всему HD из-за ограничений в режиме адресации диска - они могут использовать систему Cylinder-Head-Sector, не способную адресовать более чем первые 8 ГБ дискового пространства: http: //en.wikipedia. org / wiki / Головка блока цилиндров .

Stage2 загружает ядро в ОЗУ (опять же, с помощью дисковых утилит BIOS). Если это ядро ​​2.6+, в нем также есть скомпилированные initramfs, поэтому нет необходимости его загружать. Если это старое ядро, загрузчик также загружает автономный образ initrd в память, чтобы ядро ​​могло смонтировать его и получить драйверы для монтирования реальной файловой системы с диска.

Проблема в том, что ядро ​​(и ramdisk) весят более 1 МБ, поэтому для загрузки их в ОЗУ необходимо сначала загрузить ядро ​​до 1 МБ, затем перейти в защищенный режим (32 бита), переместить загруженное ядро ​​в верхнюю память (бесплатно). первые 1 МБ для реального режима), затем снова вернитесь в реальный (16-битный) режим, получите виртуальный диск с диска на первый 1 МБ (если это отдельный initrd и старое ядро), возможно, снова переключитесь в защищенный (32-битный) режим, поместите его туда, где он должен, возможно вернитесь в реальный режим (или нет: /programming/4821911/does-grub-switch-to-protected-mode ) и выполните код ядра. Предупреждение: я не совсем уверен в тщательности и точности этой части описания.

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

Борис Бурков
источник
Разве загрузчик не может просто загрузить ядро ​​порциями вместо перехода в защищенный режим ?? И что нужно для освобождения этого 1 МБ .. (Извините .. не смог понять это ...)
rpthms
Необходимость освобождения первого 1МБ заключается в следующем: загрузчик может получить доступ к вашему жесткому диску только в реальном режиме, поскольку он обращается к нему с помощью утилит BIOS, которые работают в реальном режиме (они работают с 16-битными аргументами и используют 16-битные операции). Реальный режим просто не видит ОЗУ, кроме как на 1 МБ. Но вам нужно загрузить ядро ​​+ initramfs в ОЗУ, и они занимают ~ 5 МБ пространства в ОЗУ. Эти утилиты BIOS просто не смогут втиснуть 5 МБ в первые 1 МБ. Таким образом, загрузчик должен скопировать их с диска в первый 1 МБ, затем перейти в защищенный режим и переместить из первой 1 МБ ОЗУ в более высокую. Это теперь понятнее? :)
Борис Бурков
1
Весь материал 1 / 1,5 / 2 стадии - жуткое наследие.
psusi
1
@CMCDragonkai Да, загрузчик stage2 находится в файловой системе (а именно в /bootразделе). На этом этапе ядро ​​не загружается - это grub's stage1.5, который обращается к stage2 в /bootфайловой системе (например, в /boot/grubфайле) через свои минималистичные драйверы файловой системы. Ядро также сможет читать из /bootраздела, но это произойдет позже, после выполнения кода grub2 и загрузки ядра, а также после того, как ядро ​​прочитает initramfs. Вы говорите об init.shinitramfs? Он находится в /bootразделе вашего жесткого диска, затем stage2 grub помещает его в оперативную память, а ядро ​​считывает его из оперативной памяти.
Борис Бурков
1
Initrd должен был быть отдельным файлом. Более новые initramfs могут быть связаны с ядром, но это не обязательно - он также может быть загружен как отдельный файл загрузчиком. Поскольку файл initramfs определяется как последовательность архивов cpio, некоторые загрузчики (например, iPXE) даже допускают несколько файлов initramfs, которые будут загружаться в память один за другим. Кроме того, некоторые дистрибутивы Linux используют имена файлов в стиле initrd для обратной совместимости, хотя в настоящее время используется настоящая технология initramfs.
TelcoM
1

Я считаю, что все сводится к тому, какие функции поддерживает конкретный загрузчик. Например. ему не нужно знать конкретную файловую систему вашего комбинированного (загрузочного + корневого) раздела. В этом случае вы просто создаете отдельный загрузочный раздел в таком состоянии, чтобы он работал с вашим загрузчиком, и любая другая сложность монтирования корневого раздела остается на ядре, а образ initrd загружается из загрузочного раздела. Bootloader знает, как получить доступ к устройствам SCSI (и другим устройствам, в зависимости от того, какой загрузчик используется) либо с помощью собственных драйверов, либо с помощью подпрограмм BIOS. Более того, он умеет читать некоторые файловые системы и т. Д.

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

Мирослав Кошкар
источник
0

Для справки: если загрузчик не загружает initrd, стоит протестировать другой загрузчик; Я просто побежал в такой ситуации , как это , когда LILO проигнорирована правильно указано Initrd среднего размера (<4Mb, одиночные ext4 корневой файловой системы на SATA SSD, GPT) и GRUB 2.00 удалось.

Процесс загрузки закончился быстро с типичным

RAMDISK: Couldn't find valid RAM disk image starting at 0.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,3)
Михаил Шигорин
источник