Процесс загрузки
Микропрограмма, записанная в чип материнской платы, инициализирует оборудование. Загрузчик отыскивает ядро и запускает его. Ядро разворачивает временную файловую систему, монтирует настоящую и передаёт управление первому процессу. Монтированием называется подключение файловой системы в общее дерево каталогов; подробно этот вопрос рассматривается в следующей главе. Каждое звено цепочки передаёт управление следующему и завершается.
Когда система не загружается, диагноз ставится по тому, в каком месте цепочка оборвалась. Экран с ошибкой загрузчика и паника ядра означают разные неисправности, и устраняются они по-разному.
Слайды к главе. Материал главы изложен также в первой части лекции «Как организован Linux» с демонстрациями в терминале; слайды лекции доступны на сайте книги и в PDF.
1. BIOS (Basic Input/Output System)
BIOS — микропрограмма, хранящаяся на чипе материнской платы (во FLASH-памяти). При включении питания процессор выполняет первую инструкцию по фиксированному адресу 0xFFFFFFF0 (reset vector), где и расположен код BIOS.
Первым делом BIOS проводит самотестирование, называемое POST (Power-On Self-Test): проверяет целостность собственной микропрограммы, инициализирует процессор, установленную память и чипсет, а затем запускает прошивки остальных устройств, видеокарты и сетевой карты. Пока видеокарта не инициализирована, выводить сообщение об ошибке некуда, поэтому о результатах POST сообщает встроенный в плату динамик. Один короткий сигнал означает успех, комбинации длинных и коротких указывают на конкретную неисправность; расшифровка, приведённая в документации к плате, у каждого производителя своя.
2. Загрузчик (Bootloader)
Задача загрузчика — найти, загрузить в оперативную память и передать управление ядру операционной системы.
Схемы загрузки
Схем две, и различаются они возможностями прошивки.
Старую схему составляют BIOS + MBR (Master Boot Record). BIOS способен только прочитать первые 512 байт диска и передать им управление. В них размещаются 446 байт первичного кода загрузчика, 64 байта таблицы разделов (не более четырёх первичных) и два байта сигнатуры 55 AA. Код из MBR отыскивает активный раздел, помеченный особым флагом, и загружает оттуда следующую ступень загрузчика, например GRUB2. Из размера полей в таблице разделов следует и главное ограничение схемы: диски больше 2 ТБ ей недоступны.
Современную схему составляют UEFI + GPT (GUID Partition Table). UEFI читает файловые системы, в первую очередь FAT32, и проверяет цифровую подпись, поставленную на загрузчик (Secure Boot). Размещать код в первых секторах диска не требуется, поскольку прошивка обращается к обычному FAT32-разделу, EFI System Partition, где загрузчики хранятся обычными файлами с расширением .efi наподобие grubx64.efi, а список загрузочных записей хранится в энергонезависимой памяти материнской платы (NVRAM). Таблица разделов GPT ограничений MBR не наследует.
Полезные команды:
- Просмотр UEFI-записей:
efibootmgr -v - Просмотр разделов:
fdisk -l
GRUB2 (Grand Unified Bootloader 2)
Самый распространённый загрузчик в Linux. Он показывает меню, в котором выбирается ядро или другая установленная система, загружает модули для работы с нужным оборудованием и файловыми системами и затем запускает выбранное ядро. Настройки хранятся в /boot/grub/grub.cfg, однако править этот файл вручную бессмысленно. Он собирается заново командой grub-mkconfig из /etc/default/grub и скриптов в /etc/grub.d/, и обновление ядра уничтожит ручную правку.
3. Ядро (Kernel)
Ядро Linux представляет собой сжатый исполняемый файл, расположенный обычно в каталоге /boot под именем vmlinuz-<версия>. Запуск осуществляется в три шага.
- GRUB загружает в оперативную память два файла: сжатый образ ядра и образ initramfs.
- Ядро распаковывается и запускается с параметрами командной строки, переданными загрузчиком (просмотреть их можно в
/proc/cmdline). - Ядро разворачивает в памяти временную корневую файловую систему, называемую initramfs.
Initramfs (Initial RAM File System)
Внутри содержатся драйверы, модули ядра, микрокод процессора и скрипты ранней загрузки, собранные в один архив, то есть всё, без чего до настоящего диска не добраться. Задача initramfs — смонтировать настоящий корень (/) и передать управление процессу init.
Промежуточная ступень необходима из-за замкнутого круга. Ядро должно смонтировать корень, но драйвер нужного контроллера или файловой системы может быть собран отдельным модулем, а модули, вынесенные из ядра, хранятся на этом корне. Замкнутый круг разрывает initramfs, содержащий всё необходимое, чтобы добраться до настоящего диска, даже если тот зашифрован или собран в RAID.
4. Init и systemd
Процесс с PID 1 (init или systemd) является прародителем всего, что работает в системе; ему же достаются осиротевшие процессы. Он запускает службы в правильном порядке, монтирует файловые системы по описанию, заданному в /etc/fstab, и следит за тем, что уже запущено.
systemd — самая распространённая сегодня реализация init. Всё, чем он управляет, описано однотипными объектами, называемыми юнитами (units). Юнитом может быть служба, точка монтирования, сокет или таймер, запускающий задачу по расписанию. Зависимости между ними показывает systemctl list-dependencies default.target, а повседневная работа сводится к двум утилитам: systemctl управляет юнитами, journalctl показывает их журналы.
Задание. Пройти загрузку вручную, от разметки диска до записи в
efibootmgr: «Установка Arch Linux вручную с RAID1 и UEFI».