Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Исследуем процесс загрузки Linux

(C) В.А.Костромин, 2007
(версия файла от 2.08.2007 г.)


Назад Оглавление Вперед

Этап 3: Загрузчик 2 этапа операционной системы

3.1. Задачи, решаемые загрузчиком

Итак, отработали маленькие программы, которые расположены в главной загрузочной записи диска (MBR) и в первом секторе активного раздела (Boot Record), то есть первичный загрузчик ОС. Код первичного загрузчика уже различен в разных операционных системах и является, как уже было сказано, частью загрузчика этой ОС (ну, или какого-то универсального загрузчика, типа GRUB). В некоторых дистрибутивах используются собственные загрузчики, например, в ASPLinux это ASPLoader. Однако рассказ о всех видах загрузчиков не является нашей целью, поэтому мы кратко рассмотрим только два из них - LILO и GRUB. LILO (LInux LOader) - это "родной" загрузчик операционной системы Linux, который, однако в последнее время все более вытесняется универсальным загрузчиком GRUB (GRand Unified Bootloader). Поскольку нас интересует не создание собственного загрузчика, а всего лишь настройка процедур загрузки системы, мы рассмотрим эту проблему на примере двух названных загрузчиков.

Главная задача, которая стоит перед загрузчиком любой операционной системы, заключается в том, чтобы перенести в память ядро операционной системы и передать этому ядру управление дальнейшим функционированием компьютера. При этом современные загрузчики позволяют выбрать ядро из нескольких возможных вариантов как одной и той же операционной системы, так и загрузить ядра разных ОС. Поскольку загрузчик второго этапа представляет собой уже досточно большую программу, ему это вполне под силу. Более того, некоторые загрузчики (в частности, GRUB) предоставляют пользователю возможность выполнения некоторых команд, то есть они представляют собой уже некоторое подобие командного процессора.

Для того, чтобы загрузить в оперативную память ядро, загрузчик второго этапа должен решить несколько сопутствующих проблем. Первая состоит в том, что код ядра размещается в виде файла на одном из физических носителей. В работающей системе доступ к файлу предоставляется через драйвер файловой системы. А как загрузчику получить доступ к этому файлу? LILO и GRUB решают эту задачу по-разному. Эти решения будут рассмотрены чуть позже, а пока вернемся к перечню проблем, стоящих перед загрузчиком.

Одна из основных задач ядра – управление тем «железом», которое составляет аппаратную часть компьютера. Поэтому ядро после запуска производит опрос «железа» с целью определить, какие устройства присутствуют в системе. Если драйвер найденного устройства вкомпилирован в ядро, устройство инициализируется. Однако маловероятно, что стандартное ядро, заготовленное разработчиком дистрибутива, содержит драйверы для всех устройств, имеющихся в вашем компьютере. Для этого разработчикам пришлось бы создать ядро огромного размера, причем большая часть кода такого ядра была бы простым балластом, поскольку в реальных системах никогда бы не использовалась. Значит, драйверы устройств, отсутствующие в ядре, надо загрузить из соответствующих файлов. После загрузки ядро должно запустить процесс init, который, как известно, является родональником всех остальных процесов в системе. Код программы init лежит где-то на носителе, доступ к которому тоже предоставляет файловая система.

Но файловая система не является частью ядра, драйвер файловой системы надо загрузить с того же диска. Когда-то вариантов выбора для корневой файловой системы в Linux, можно сказать, не было. И размещалась она либо на дискете, либо на одном из разделов жесткого диска. Поэтому достаточно было указать загрузчику местоположение корневой файловой системы (что достигается заданием параметра типа "root=/dev/hda2") и проблема решалась. В наше время загрузочным устройством может оказаться устройство самого разного вида: SCSI, SATA, RAID-массивы, CD- или DVD-ROM, USB (причем USB-портов может быть несколько, надо еще выбрать, которое из этих устройств загрузочное). Корневая файловая система на загрузочном устройстве может быть самого разного типа (fat, ext2, reiserfs и так далее), может быть сжата, зашифрована и так далее. Возможно, что она даже расположена на сервере сети, ядру требуется провести присвоение адреса по DHCP, произвести DNS поиск и установить соединение с удаленным сервером (с именем и паролем), все это до того, как ядро сможет найти и выполнить первую программу пространства пользователя. Ситуация усугубляется еще и тем, что драйверы некоторых устройств могут конфликтовать друг с другом, так что загрузить их в память одновременно (например, если они включены в одно и то же ядро) невозможно.

Получается замкнутый круг: чтобы подключить загрузочное устройство, надо получить доступ к файловой систем, а для этого надо подключить загрузочное устройство.

Решение этой проблемы было найдено за счет временного подключения виртуальной файловой системы, образ которой хранится в файле рядом с образом ядра. При этом минимальное число самых необходимых драйверов включается в само ядро, а все остальные размещаются на виртуальном диске, в виде подгружаемых модулей. Когда осуществляется загрузка (в частности, на неизвестном оборудовании) ядро опрашивает аппаратуру и загружает только те модули, которые соответствуют обнаруженной конфигурации. Впервые такое решение было применено в ядре версии 1.3.73, и с некоторыми модификациями используется до настоящего времени как для запуска процедуры инсталляции, так и в процессе штатной загрузки системы. В частности, и LILO и GRUB создают в оперативной памяти виртуальный диск и разворачивают на нем временную корневую файловую систему, содержащую необходимые ядру драйверы устройств и служебные файлы. Сжатый образ этой файловой системы обычно располагается в одном каталоге с образом ядра в виде файла, содержащего дополнительные компоненты, например, драйверы некоторых устройств. Только способ организации виртуального диска в ядрах серий 2.4.х и 2.6.х различен. Но эти различия мы рассмотрим в следующем подразделе.

Еще одной задачей, выполняемой загрузчиком второго этапа, является передача ядру значений аргументов, которые пользователь пожелал переопределить. К числу таких аргументов относятся, например, уровень выполнения или имя программы, которую ядро должно запустить вместо запускаемого по умолчанию процесса init. Вообще говоря, обычно передавать ядру какие-либо параметры и не требуется - принятые по умолчанию значения хорошо срабатывают в большинстве случаев. Изменять эти значения приходится тем пользователям, которые вынуждены оптимизировать ядро под их конкретную машину, или тем, кто создает свое собственное ядро для поддержки редкого оборудования, автоматическое определение которого по тем или иным причинам невозможно.

Чтобы понять, каким образом загрузчик решает перечисленные проблемы, давайте заглянем в каталог /boot в дереве каталогов вашей файловой системы. Вы знаете, что этот каталог содержит файлы, используемые в процессе загрузки. Можете вы объяснить назначение всех файлов, находящихся в этом каталоге? Если вы ответите «да», то вам не стоит тратить время на чтение моих заметок. А всех остальных я приглашаю просмотреть содержимое этого каталога. Оно может несколько отличаться о того, что я увидел, например, на компьютере с ASP Linux 11:

Листинг 1. Содержимое каталога /boot

 [kos@trend /boot] # ls -l
total 3499
-rw-r--r--  1 root root   62293 Jan 23  2006 config-2.6.14-1.1653.1asp
drwxr-xr-x  2 root root    1024 Aug 31  2006 grub
-rw-r--r--  1 root root 1101106 Apr 29  2006 initrd-2.6.14-1.1653.1asp.img
drwx------  2 root root   12288 Apr 29  2006 lost+found
lrwxrwxrwx  1 root root      29 Apr 29  2006 System.map -> System.map-2.6.14-1.1653.1asp
-rw-r--r--  1 root root  806603 Jan 23  2006 System.map-2.6.14-1.1653.1asp
lrwxrwxrwx  1 root root      26 Apr 29  2006 vmlinuz -> vmlinuz-2.6.14-1.1653.1asp
-rw-r--r--  1 root root 1569945 Jan 23  2006 vmlinuz-2.6.14-1.1653.1asp

Как видите, тут только 4 файла (подкаталоги и символические ссылки не считаем): config-2.6.14-1.1653.1asp, initrd-2.6.14-1.1653.1asp.img, System.map-2.6.14-1.1653.1asp и vmlinuz-2.6.14-1.1653.1asp.

Файл vmlinuz-2.6.14-1.1653.1asp представляет собой образ ядра, которое загрузчик должен перенести в оперативную память. В принципе здесь может размещаться несколько разных файлов с образами ядер. Но это в том случае, если вы проводили обновление системы или самостоятельно ставили какое-то ядро. Символическая ссылка с именем vmlinuz указывает на то ядро, которое будет запускаться.

Файл config-2.6.14-1.1653.1asp для нас пока интереса не представляет - в нем сохранены параметры и опции, которые были использованы при компиляции этого ядра. Он может пригодиться, если вы вздумаете перекомпилировать ядро под свое оборудование. В таком случае этот файл может несколько облегчить процедуру компиляции.

А вот два оставшихся файла непосредственно используются в процессе загрузки, поэтому мы должны поговорить о них подробнее. И начнем с рассмотрения файла /boot/initrd-2.x.yy-что-то-там.img.


Назад Оглавление Вперед