... И всё начинается с рестарта.
Загрузка и инициализация системы

Глава из книги Сага о FreeBSD

Алексей Федорчук

2008-10-29


Содержание

В этой главе мы рассмотрим процессы загрузки и инициализации FreeBSD последовательно — от включения машины до появления приглашения к авторизации в консоли или в менеджере сеансов графического режима.

Введение

Старт системы распадается на два этапа, лишь опосредованно связанных между собой — собственно загрузку ее и инициализацию.

Под загрузкой операционной системы понимается запуск на исполнение специальной программы, которая называется образом ядра системы (или просто ядром). Образ ядра — почти обычный бинарный исполняемый файл. И специфика его запуска — только в том, что, если любые другие программы запускаются под управлением какой-либо ОС, считываясь с файловой системы, которую эта ОС воспринимает в качестве родной (native), то ядро обязано запуститься как бы само собой, без всякой операционной системы (ибо оно-то и есть операционная система), и с носителя, о котором система ничего не знает (поскольку сама она еще не загружена). Не случайно в англоязычной литературы для процесса загрузки существует общепринятая метафора bootstrapping, что столь же аллегорически можно перевести как "поднятие себя за шнурки своих ботинок". И хотя в реальной жизни такое не каждому удается, в мире POSIX-систем эта процедура осуществляется регулярно — и, как правило, успешно.

Образ ядра системы содержит все необходимое для чистого bootstrapping'а. Однако выполнить его таким образом можно только с носителя без файловой системы. И потому прямой запуск ядра, насколько я знаю, используется только при загрузке с дискеты. При обычном же старте ОС с винчестера в этом деле участвует и некая внешняя сила — специальная программа, называемая загрузчиком. Она загружает ядро системы, отвечает за определение оборудования, подгрузку объектных модулей (загружаемых модулей ядра) и монтирование корневой файловой системы (в режиме "только для чтения"). Ядро же тем временем запускает системные (то есть не связанные с исполняемыми файлами) процессы, управляющие виртуальной памятью, буферами, страницами памяти и т.д., вплоть до swapper'а, а по завершении — первый "обычный" (то есть ассоциированный с исполняемым файлом на диске) процесс init (/sbin/init).

Вслед за тем в действие вступает система инициализации. Ее роль — обеспечить, посредством соответствующих стартовых скриптов (они же — сценарии инициализации), монтирование файловых систем (и перемонтирование корня в режиме "чтения/записи"), запуск основных системных сервисов, или демонов, вызов команд для получения терминала (процессы типа getty -- от get terminal, то есть получение терминала) и авторизации пользователей (login). Окончание старта системы и знаменуется приглашением к авторизации.

Зрительно этапы загрузки и инициализации отличаются тем или иным визуальным представлением выводимых сообщений. Так, во FreeBSD, например, сообщения о ходе загрузки выводятся символами радикально белого цвета, сменяемыми на этапе инициализации обычным приглушенно-белым.

Загрузка и инициализация — это первое, что в любой ОС видит пользователь. Правда, пользователю POSIX-совместимой системы такое удовольствие выпадает много реже, чем "подоконнику". Нормальный режим эксплуатации домашней Unix-машины — это ее включение рано утром и выключение — поздно вечером. (Правда, представления о "рано" и "поздно" у всех свои). А служебная Unix-машина по-хорошему выключаться вообще не должна — вплоть до полной физической амортизации. Ну а необходимость в рестарте системы по ходу работы во FreeBSD возникает чрезвычайно редко. Собственно, только после пересборки и реинсталляции нового ядра (или переносе корневого раздела — но это уже вообще исключительный случай) — во всех прочих случаях реконфигурирования системы можно обойтись и без этого.

Так что, казалось бы, что за дело пользователю до того, как протекает старт системы, и сколь долго он длится? Тем не менее, некоторые действия по настройке обоих этапов этого процесса бывают необходимыми. Ибо при старте системы не только выводится некоторая заставка и, возможно, меню с вариантами загрузки, но и подгружаются модули ядра, соответствующие наличному оборудованию, монтируются файловые системы, запускаются сценарии инициализации, открываются виртуальные терминалы, и так далее, и тому подобное. Конечно, безусловно обязательным из всех этих действий является только собственно загрузка ядра — прочие могут быть выполнены и впоследствии. Однако не лучше ли настроить систему так, чтобы сразу по окончании процедуры ее старта получить полностью готовую к употреблению систему, нежели потом доводить ее вручную до этого состояния?

Кроме того, понимание хода загрузки и инициализации будет не лишним при ручном вмешательстве в этот процесс. А необходимость такого вмешательства — увы — время от времени возникает в аварийных ситуациях...

Так что давайте проследим основные стадии загрузки и инициализации FReeBSD и посмотрим, что в них подлежит настройке, а также где и как (а главное — зачем) в них можно вмешаться.

О загрузке и загрузчиках

Начать изучение старта системы резонно с первого ее этапа — а именно, собственно загрузки. Как уже было сказано, управление этим этапом осуществляет специальная программа, которая по-русски так и называется – загрузчик, хотя в английском для нее употребляется два термина — loader и boot manager (что, как мы увидим со временем, немного разные вещи, но сейчас это не принципиально).

На самом деле любой загрузчик включает в себя две или даже три относительно независимые части — даже если он распространяется в виде единого пакета, как Lilo или GRUB. Чтобы убедиться в этом, представим себе, как происходит запуск машины на "железном", так сказать, уровне (имеется в виду — intel-совместимой персоналки, на иных архитектурах все обстоит несколько иначе).

Перво-наперво после включения питания запускается программа, прошитая в ПЗУ компьютера (BIOS). Она выполняет проверку железа, после чего отыскивает носитель, установленный в BIOS Setup в качестве первого загрузочного устройства (для определенности предположим, что это — винчестер), на нем — первый физический блок, содержащий так называемую главную загрузочную запись (MBR — Master Boot Record).

Содержимое MBR — это, во-первых, сигнатура диска размером в 2 байта. Во-вторых -- таблица дисковых разделов, тех самых четырех, каждый по 16 байт, в один из которых мы ранее установили FreeBSD, а другие -- либо не используются, либо занятым более иными ОСями. А в-третьих — некий код, принимающий на себя управление от BIOS по окончании его работы. В стандартном MBR — том, что записан на "свежевкрученном" винчестере или восстанавливается после DOS-команды FDISK /mbr, — этот код только и может, что отыскать первый физический раздел диска (primary partition) и передать управление на его загрузочный сектор. Чего вполне достаточно для загрузки операционок вроде DOS или Windows 9X/ME с первого (или единственного) раздела. Но явно мало в любом другом случае — например, если на диске установлено несколько ОС, которые, естественно, не могут уместиться в одном разделе.

Поэтому в состав любого загрузчика, претендующего на мультисистемность, должна входить собственная программа, записываемая в MBR. Поскольку объем последнего — всего 512 байт (размер физического дискового блока), из которых 66 байт уже занято под сигнатуру и таблицу разделов, особо богатых функций в эту программу не вместить. Обычно она способна на то, чтобы опознать все задействованные (used) первичные разделы, вывести их список и позволить пользователю выбрать раздел для загрузки, после чего передать управление на загрузочный сектор выбранного раздела. Либо -- отыскать специальную программу загрузчик, которая и выполнит все дальнейшие действия (в том числе вывод списка возможных вариантов загрузки).

Подобно MBR, загрузочный сектор раздела (Boot Record — уже не Master!) содержит информацию о его разметке (Disk Label), зависящую от используемой в данной ОС ее схемы. Есть в нем и управляющий код, принимающий эстафету от программы, записанной в MBR. И вот этот код — вторая составная часть загрузчика. Правда, и ее возможности также не могут быть богатыми — ведь размер загрузочного сектора раздела составляет те же 512 байт, часть из которых опять-таки занята служебной информацией (о начале и конце раздела, идентификаторе типа файловой системы, и так далее). И потому на нее возлагается одна-единственная функция — передать управление программе, лежащей за пределами загрузочного сектора. Которая, собственно, и должна опознать корневой раздел ОС и несомую им файловую систему, после чего, прямо или опосредованно, загрузить ее ядро.

Легко догадаться, что первые две составляющие загрузчика, в сущности, не имеют отношения ни к какой операционке, и не являются частями файловой системы вообще. А вот с третьей — возможны варианты. Она может входить в файловую иерархию загружаемой ОС, как Lilo, или представлять собой нечто вроде самостоятельной мини-ОС, как GRUB (не случайно его настоятельно рекомендуют устанавливать в собственный дисковый раздел, не монтируемый по умолчанию к корню любой из загружаемых им операционок). А как обстоит дело с устройством загрузчика нашей героини — FreeBSD?

вперед