Библиотека сайта rus-linux.net
Введение в процесс загрузки и запуска Linux
Оригинал: An introduction to the Linux boot and startup processes
Автор: David Both
Дата публикации: 20 февраля 2017 года
Перевод: А. Кривошей
Дата перевода: март 2018 г.
Понимание процессов загрузки и запуска Linux важно для того, чтобы понимать, как правильно настроить систему, или решить проблемы с загрузкой. В этой статье представлен обзор последовательности загрузки системы с использованием загрузчика
На самом деле, есть две последовательности событий, которые необходимы для загрузки Linux-компьютера и делают его пригодным для использования: загрузка и запуск. Последовательность загрузки начинается, когда компьютер включен, и завершается, когда инициализируется ядро и запускается systemd. Затем процесс запуска завершает задачу приведения компьютера Linux в рабочее состояние.
В целом, процесс загрузки и запуска Linux довольно прост для понимания. Он состоит из следующих этапов, которые более подробно будут описаны в следующих разделах.
- BIOS POST;
- загрузчик (GRUB2);
- инициализация ядра;
- запуск systemd, родительского компонента всех процессов.
Обратите внимание, что в этой статье рассматриваются GRUB2 и systemd, поскольку они являются текущим загрузчиком и системой инициализации для большинства главных дистрибутивов. Ранее использовались другие варианты таких программ, и они все еще используются в некоторых дистрибутивах.
Процесс загрузки
Процесс загрузки может быть инициирован одним из нескольких способов. Во-первых, если питание отключено, его включение запустит процесс загрузки. Если компьютер уже запущен, локальный пользователь, включая root или обычного пользователя, может программно инициировать последовательность загрузки с помощью графического интерфейса или командной строки для перезагрузки компьютера. Сначала компьютер будет выключен, а затем перезагружен.
BIOS POST
Первый этап процесса загрузки Linux на самом деле не имеет ничего общего с Linux. Это аппаратная часть процесса загрузки и она одинаковая для любой операционной системы. Когдана компьютер подается питание, он запускает процедуру POST (Power On Self Test), которая является частью BIOS (Basic I/O System).
Когда IBM разработала первый компьютер, еще в 1981 году, для инициализации аппаратных компонентов был разработан BIOS. POST является частью BIOS, задачей которого является обеспечение правильного функционирования оборудования. Если POST не сработал нормально, компьютер может не использоваться, поэтому процесс загрузки не будет продолжен.
BIOS POST проверяет базовую работоспособность аппаратного обеспечения, а затем выдает прерывание BIOS, INT 13H, которое находит загрузочные секторы на всех подключенных загрузочных устройствах. Первый загрузочный сектор с правильной загрузочной записью, который он находит, загружается в ОЗУ, а затем управление передается коду, загруженному из загрузочного сектора.
Загрузочный сектор - это фактичеки первый этап загрузчика. Существует три загрузчика, используемые большинством дистрибутивов Linux: GRUB, GRUB2 и LILO. GRUB2 является самым современным и используется сегодня гораздо чаще, чем более старые варианты.
GRUB2
GRUB2 означает «GRAND Unified Bootloader, версия 2», и сегодня он является основным загрузчиком для большинства дистрибутивов Linux. GRUB2 - это программа, которая делает компьютер достаточно умным, чтобы найти ядро операционной системы и загрузить его в память. Поскольку проще писать и говорить GRUB, чем GRUB2, я буду использовать термин GRUB в этом документе, но при этом буду ссылаться на GRUB2, если не указано иное.
GRUB был разработан для совместимости с спецификацией multiboot, которая позволяет GRUB загружать множество версий Linux и других бесплатных операционных систем; он также может загружать загрузочную запись проприетарных операционных систем.
GRUB также позволяет пользователю выбирать загрузку одного из нескольких разных ядер для любого дистрибутива Linux. Это дает возможность загрузиться с предыдущей версией ядра, если обновленная версия работает некорректно или несовместима с частью программного обеспечения. GRUB можно настроить с помощью файла /boot/grub/grub.conf.
GRUB1 теперь считается устаревшим и был заменен в большинстве современных дистрибутивов на GRUB2, который является переписанным GRUB1. Дистрибутивы на основе Red Hat были обновлены до GRUB2, начиная с Fedora 15 и CentOS/RHEL 7. GRUB2 обеспечивает ту же функциональность, что и GRUB1, но GRUB2 также обеспечивает большую гибкость на этапе предварительной загрузки. GRUB2 настраивается с помощью файла /boot/grub2/grub.cfg.
Основная функция GRUB заключается в том, чтобы загрузить ядро Linux в память и запустить его. Обе версии GRUB работают в целом одинаково и процесс включает те же три этапа, но я буду использовать GRUB2. Настройка GRUB или GRUB2 и использование команд GRUB2 выходит за рамки данной статьи.
Хотя GRUB2 официально не использует нотацию этапов для трех этапов загрузки GRUB2, удобно обращаться к ним таким образом, что я и буду делать в этой статье.
Этап 1
Как упоминалось в разделе POST BIOS, в конце POST BIOS просматривает прикрепленные диски в поиске загрузочной записи, обычно находящейся в главной загрузочной записи (MBR), загружает первую обнаруженную в ОЗУ, а затем начинает выполнение загрузочной записи. Код начальной загрузки, т. е. этап 1 GRUB2, очень мал, поскольку он должен помещаться в первый 512-байтовый сектор на жестком диске вместе с таблицей разделов. Общий объем пространства, выделенного для реального кода начальной загрузки в классическом общем MBR, составляет 446 байтов. Файл размером 446 байт для этапа 1 называется boot.img и не содержит таблицу разделов, которая добавляется в загрузочную запись отдельно.
Поскольку загрузочная запись должна быть такой маленькой, она не очень умна и не понимает структуры файловой системы. Поэтому единственной целью этапа 1 является нахождение и загрузка этапа 1.5. Для этого этап 1.5 GRUB должен быть расположен в пространстве между самой загрузочной записью и первым разделом на диске. После загрузки этапа 1.5 GRUB в ОЗУ, этап 1 передает управление этапу 1.5.
Этап 1.5
Как упоминалось выше, этап 1.5 GRUB должен быть расположен в пространстве между самой загрузочной записью и первым разделом на диске. По техническим причинам исторически это пространство не использовалось. Первый раздел на жестком диске начинается в секторе 63 с MBR в секторе 0, что оставляет 62 512-байтовых секторов - 31 744 байта, в которых хранится файл core.img, который является этапом 1.5 GRUB. Размер файла core.img равен 25389 байт, поэтому между MBR и первым дисковым разделом имеется много свободного места для его хранения.
Из-за большего количества кода, который может быть задействован для этапа 1.5, он может содержать несколько драйверов для распространенных файловых систем, таких как EXT и других файловых систем Linux, FAT и NTFS. GRUB2 core.img гораздо более сложный и интеллектуальный по сравнению с более старым этапом 1.5 GRUB1. Это означает, что этап 2 GRUB2 может быть расположен на стандартной файловой системе EXT, но не может быть расположен на логическом томе. Таким образом, стандартное расположение файлов этапа 2 - файловая система /boot, а именно /boot/grub2.
Обратите внимание, что каталог /boot должен находиться в файловой системе, поддерживаемой GRUB. Не все файловые системы подходят для него. Функция этапа 1.5 - загрузить драйвера файловой системы, необходимыми для поиска файлов этапа 2 в файловой системе /boot и загрузки необходимых драйверов.
Этап 2
Все файлы этапа 2 GRUB находятся в каталоге /boot/grub2 и нескольких его подкаталогах. GRUB2 не имеет файла образа, как этапы 1 и 2. Вместо этого он состоит в основном из модулей ядра, которые загружаются по мере необходимости из каталога /boot /grub2/ i386-pc.
Функция этапа 2 GRUB2 состоит в том, чтобы найти и загрузить ядро Linux в оперативную память и переключить управление компьютером на ядро. Ядро и связанные с ним файлы находятся в каталоге /boot. Файлы ядра могут быть идентифицированы, поскольку все их имена начинаются с vmlinuz. Вы можете просмотреть содержимое каталога /boot, чтобы увидеть установленные в вашей системе ядра.
GRUB2, как и GRUB1, поддерживает загрузку из одного из ядер Linux. Менеджер пакетов Red Hat, DNF, поддерживает сохранение нескольких версий ядра, поэтому, если возникает проблема с самой новой версией, можно загрузить более старую версию ядра. По умолчанию GRUB предоставляет предварительное загрузочное меню установленных ядер, включая вариант безопасной загрузки и, если он настроен, вариант восстановления.
Этап 2 GRUB2 загружает выбранное ядро в память и передает управление компьютером ядру системы.
Ядро
Все ядра хранятся в формате самораспаковывающегося архива для экономии места. Ядра расположены в каталоге /boot вместе с исходным образом RAM-диска и картами устройств жестких дисков.
После того, как выбранное ядро загрузится в память и начнет выполнение, оно должно сначала извлечь себя из архива, прежде чем сможет выполнить любую полезную работу. После того, как ядро извлекло себя, оно загружает systemd, заменившую старую программу SysV init, и переключает управление на нее.
Это конец процесса загрузки. К этому моменту ядро Linux и systemd работают, но не могут выполнять какие-либо продуктивные задачи для конечного пользователя, потому что ничего не работает.
Процесс запуска
Процесс запуска следует за процессом загрузки и приводит компьютер Linux в рабочее состояние, в котором он может использоваться для продуктивной работы.
systemd
systemd является матерью всех процессов, и она отвечает за то, чтобы привести систему Linux в состояние, в котором на ней можно работать. Некоторые из ее функций, которые намного шире, чем у старой программы init, предназначены для управления различными аспектами работающей системы Linux, включая создание файловых систем, а также запуск и управление системными службами, необходимыми для повседневной работы Linux. Любая из задач systemd, не относящихся к последовательности запуска, выходит за рамки этой статьи.
Во-первых, systemd монтирует файловые системы, заданные в /etc/fstab, включая любые файлы или разделы подкачки. На этом этапе она может получить доступ к конфигурационным файлам , расположенным в /etc, включая ее собственный. Она использует свой конфигурационный файл , /etc/systemd/system/default.target, для определения состояния (цели), в которые он должен загружать систему. Файл default.target является только символической ссылкой на настоящий целевой файл. Для рабочей станции или настольных компьютеров это обычно будет graphical.target, что эквивалентно уровню запуска 5 в старой системе инициализации SystemV. Для сервера по умолчанию, скорее всего, это будет multi-user.target, который похож на уровень запуска 3 в SystemV. Emergency.target похож на однопользовательский режим.
Обратите внимание, что цели и службы являются единицами systemd.
В таблице 1 ниже представлено сравнение целей systemd со старыми уровнями запуска SystemV. Алиасы целей предоставляются systemd для обратной совместимости. Алиасы целей позволяют сценариям и многим системным администраторам, таким как я, использовать команды SystemV, такие как init 3, для изменения уровней запуска. Конечно, команды SystemV для интерпретации и выполнения пересылаются в systemd.
Уровень SystemV | Цели target | Алиасы целей systemd | Описание |
---|---|---|---|
- | halt.target | - | Выключает систему без выключения питания. |
0 | poweroff.target | runlevel0.target | Выключает систему с выключением питания. |
S | emergency.target | - | Однопользовательский режим. Службы не работают; файловые системы не смонтированы. Это базовый уровень работы с только аварийной оболочкой, запущенной на главной консоли, чтобы пользователь мог взаимодействовать с системой. |
1 | rescue.target | runlevel1.target | Базовая система, включающая смонтированные файловые системы только с основными запущенными службами и аварийной оболочкой на главной консоли. |
2 | - | runlevel2.target | Многопользовательский режим без NFS, но с запущенными остальными консольными службами |
3 | multi-user.target | runlevel3.target | Все службы работают, но доступен только интерфейс командной строки. |
4 | - | runlevel4.target | Не используется |
5 | graphical.target | runlevel5.target | Многопользовательский режим с графическим интерфейсом |
6 | reboot.target | runlevel6.target | Перезагрузка |
- | default.target | - | Эта цель всегда является символической ссылкой на multi-user.target или graphical.target. system всегда использует default.target для запуска системы. default.никогда не должна ссылаться на halt.target, poweroff.target или reboot.target. |
Таблица 1: Сравнение уровней запуска SystemV с целями systemd.
Каждая цель имеет набор зависимостей, описанных в конфигурационном файле. systemd запускает необходимые зависимости. Эти зависимости - службы, необходимые для запуска хоста Linux на определенном уровне функциональности. Когда все зависимости, перечисленные в целевых конфигурационных файлах, загружаются и запускаются, система работает на этом целевом уровне.
systemd также просматривает устаревшие каталоги инициализации SystemV, чтобы узнать, имеются ли там файлы запуска. Если они есть, systemd использует их в качестве конфигурационных файлов для запуска служб, описанных в этих файлах. Устаревшая сетевая служба является хорошим примером одного из тех случаев, когда в Fedora все еще используются файлы запуска SystemV.
Рисунок 1, ниже, скопирован непосредственно с man-страницы bootup. Он показывает общую последовательность событий во время запуска systemd и основные требования к их порядку для обеспечения успешного запуска.
Цели sysinit.target и basic.target можно рассматривать как контрольные точки в процессе запуска. Хотя одной из целей разработки systemd было обеспечение одновременного запуска системных служб, все еще есть определенные службы и функциональные цели, которые необходимо запустить, прежде чем можно будет запустить другие службы и цели. Эти контрольные точки не могут быть пройдены до тех пор, пока не будут выполнены все требуемые службы и цели.
Таким образом, sysinit.target достигается, когда завершены все компоненты, от которых он зависит. Монтирование файловых систем, настройка файлов подкачки, запуск udev, установка генератора случайных чисел, запуск низкоуровневых служб и настройка криптографических служб, если одна или несколько файловых систем зашифрованы, должны быть завершены, но внутри sysinit.target эти задачи могут выполняться параллельно.
Sysinit.target запускает все низкоуровневые службы и компоненты, необходимые для минимальной функциональности системы, и которые будут необходимы для перехода на basic.target.
local-fs-pre.target | v (various mounts and (various swap (various cryptsetup fsck services...) devices...) devices...) (various low-level (various low-level | | | services: udevd, API VFS mounts: v v v tmpfiles, random mqueue, configfs, local-fs.target swap.target cryptsetup.target seed, sysctl, ...) debugfs, ...) | | | | | \__________________|_________________ | ___________________|____________________/ \|/ v sysinit.target | ____________________________________/|\________________________________________ / | | | \ | | | | | v v | v v (various (various | (various rescue.service timers...) paths...) | sockets...) | | | | | v v v | v rescue.target timers.target paths.target | sockets.target | | | | v \_________________ | ___________________/ \|/ v basic.target | ____________________________________/| emergency.service / | | | | | | v v v v emergency.target display- (various system (various system manager.service services services) | required for | | graphical UIs) v | | multi-user.target | | | \_________________ | _________________/ \|/ v graphical.target
Рисунок 1: Карта запуска systemd.
После того, как будет выполнен sysinit.target, systemd запустит basic.target, запуская все компоненты, необходимые для его выполнения. basic.target обеспечивает некоторую дополнительную функциональность, запуская компоненты, которые необходимы для следующей цели. Они включают настройку таких аспектов, как пути к различным исполняемым каталогам, коммуникационные сокеты и таймеры.
Наконец, могут быть инициализированы цели пользовательского уровня, multi-user.target или graphical.target. Обратите внимание, что многопользовательский режим должен быть достигнут до того, как будут выполнены графические зависимости.
Подчеркнутые цели на рисунке 1 являются обычными целями запуска. Когда достигнута одна из этих целей, запуск завершен. Если значением по умолчанию является параметр multi-user.target, вы должны увидеть логин в текстовом режиме на консоли. Если значением по умолчанию является graphical.target, вы должны увидеть графический экран входа в систему; конкретный экран входа, который вы видите, будет зависеть от используемого по умолчанию диспетчера сеансов.
Проблемы
Недавно мне пришлось менять ядро по умолчанию на компьютере под Linux, использующем GRUB2. Я обнаружил, что некоторые из команд, похоже, не работают должным образом, или может быть я использовал их неправильно. Я еще не уверен в причинах, нужно сделать еще несколько тестов.
Команда grub2-set-default неправильно настроила индекс ядра по умолчанию в файле /etc/ default/grub, поэтому нужное мне альтернативное ядро не загрузилось. Далее я вручную изменил /etc/default/grub GRUB_DEFAULT=saved на GRUB_DEFAULT=2, где 2 - индекс установленного ядра, которое я хотел загрузить. Затем я запустил команду grub2-mkconfig> /boot/grub2/grub.cfg, чтобы создать новый конфигурационный файл grub. Этот обходной метод сработал так, как я ожидал, и загрузил альтернативное ядро.
Заключение
GRUB2 и система systemd являются ключевыми компонентами на этапах загрузки и запуска большинства современных дистрибутивов Linux. Эти два компонента работают вместе, чтобы сначала загрузить ядро, а затем запустить все системные службы, необходимые для создания полнофункциональной системы Linux.
Хотя я нахожу GRUB2 и systemd более сложными, чем их предшественники, они досточно легко изучаются и управляются. В man-страницах есть много информации о systemd, а на freedesktop.org есть полный набор