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

UnixForum






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

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

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

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


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

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

3.5. Загрузчик GRUB

Как уже говорилось выше, в последнее время вместо LILO все чаще используется GRUB (the GRand Unified Bootloader). Его первоначальная версия была разработана Э.Болейном (Erich Boleyn), а широкая популярность пришла к нему после того, как к разработке подключились Gordon Matzigkeit и Okuji Yoshinori (не решаюсь написать их имена в русской транскрипции). В настоящее время GRUB является частью проекта GNU.

Преимущества GRUB обусловлены тем, что он реализует спецификацию многовариантной загрузки (Multiboot Specification) и изначально (в отличие от LILO) разрабатывался с ориентацией на загрузку различных операционных систем. Однажды установив GRUB на жесткий диск вашего компьютера вы уже не должны будете переустанавливать его после замены версии ядра или внесения изменений в существующее ядро. Изменение конфигурации системы, добавление новых вариантов загрузки осуществляется просто редактированием конфигурационного файла. При этом GRUB умеет работать с некоторыми самыми распространенными файловыми системами, что позволяет обеспечить загрузку ядра по имени файла, не прибегая к указанию физического адреса ядра на диске. Но самое существенное - это означает, что для GRUB не существует проблемы больших дисков. Кроме того, GRUB предоставляет пользователю небольшую bash-подобную оболочку, в которой можно выполнить ряд команд, не загружая систему полностью (впрочем, эту оболочку можно вызвать и после загрузки системы из командной строки bash). Как и LILO последних версий, GRUB может работать через текстовый интерфейс, либо использовать интерфейс в виде меню.

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

Как GRUB именует диски?

GRUB использует следующий формат имен дисковых разделов:
(hdn,p)
где n - это номер диска (нумерация начинается с 0), а p - номер раздела на диске (опять же, начиная с 0). Например, второй раздел на третьем жестком диске будет обозначаться как:
(hd2,1)

Для операционных систем, которые используют разбиение разделов диска на подразделы (как, например, во FreeBSD) добавляется еще третье поле - буквенное обозначение подраздела:

(hd0,0,a)

Обратите внимание на то, что запятая и скобки обязательны - это неотъемлемая часть названия раздела жесткого диска в GRUB. Как правило, IDE диски в нумерации предшествуют SCSI-дискам, то есть под нулевым номером идет первый диск (Master) на первом IDE-контроллере, далее - второй диск (Slave) на первом контроллере и так далее. SCSI-диски следуют по порядку за последним IDE-диском.

Где размещается GRUB?

Если все файлы загрузчика LILO обычно располагаются в каталоге /boot, то GRUB размещается "этажом ниже", в каталоге /boot/grub. Давайте заглянем в этот каталог и посмотрим, что там находится.

Первым делом обратите внимание на файлы stage1 и stage2. Это и есть две основных части загрузчика, о которых мы говорили выше. Файл stage1 - это первичный загрузчик, который записывается в загрузочный сектор (проверьте - размер это файла равен 512 байтам), а stage2 - вторичный загрузчик (посмотрите размер этого файла), задача которого - загрузить ядро и файл initrd.

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

reiserfs_stage1_5  
e2fs_stage1_5  
iso9660_stage1_5  
ufs2_stage1_5
fat_stage1_5   
jfs_stage1_5	 
vstafs_stage1_5
ffs_stage1_5   
minix_stage1_5	 
xfs_stage1_5
Эти файлы - "изюминка" GRUB. Насколько я понимаю, в каждом из них содержится что-то вроде драйвера одной из файловых систем. Их называют загрузчиками полуторного этапа. Их назначение состоит в том, чтобы обеспечить загрузчику второго этапа возможность читать последующие данные средствами, предоставляемыми файловыми системами. Именно полуторный загрузчик обеспечивает основные преимущества GRUB:
  • реконфигурация загрузчика не требует перезаписи главной загрузочной записи;
  • предназначенные для загрузки ядра адресуются обычным для файловых систем способом;
  • физические операции над содержимым диска (дефрагментация, перенос файлов), никак не отражаются на работе загрузчика;
  • логическая адресация объектов загрузки делает возможным управление ими не только по заранее определённому сценарию, но и в интерактивном режиме. И возможность эта реализована в виде командного режима работы GRUB.

Кроме основных модулей stage1 и stage2 может присутствовать еще несколько, более специфических: stage2_eltorito для установки GRUB на компакт-диск, nbgrub и pxegrub для сетевой загрузки.

Задача stage1 в том, чтобы загрузить stage2 или stage1_5 с диска. При этом, размещение этих файлов кодируется в терминах цилиндр/головка/сектор, и значит на этом этапе еще не требуется распознавание типа файловой системы.

После загрузки stage1_5 и stage2 GRUB получает доступ к файловой системе на диске, а значит, получает возможность не только загрузить ядро, но и прочитать конфигурационный файл, найти и вывести фоновую картинку-заставку (она хранится в файле splash.xpm.gz), может выполнить команды своей оболочки.

Стоит отметить, что если запись stage1_5 по каким-либо причинам недоступна, то вторичный загрузчик может найти ядро по его физическому адресу. То есть, в этом случае GRUB использует методологию своих предшественников типа LILO.

В каталоге /boot/grub находится еще файл device.map, который содержит соответствия между именами дисков, применяемыми GRUB, и именами дисков, которые понятны операционной системе. Например, у меня этот файл состоит из одной строки

(hd0) /dev/hda
Необходимость наличия этого файла обусловлена тем, что в BIOS имеется возможность поменять последовательность загрузки между IDE и SCSI-дисками. Вы можете при необходимости редактировать этот файл, а также добавить в него свои комментарии, поскольку при обращении к нему оболочка GRUB игнорирует любую строку, начинающуюся символом #.

Последний из файлов, расположенных в каталоге /boot/grub/, - это файл /boot/grub/grub.conf (или menu.lst для некоторых версий), с помощью которого осуществляется конфигурирование GRUB. О том, как осуществляется настройка загрузки посредством этого файла мы сейчас и поговорим.

Конфигурирование GRUB

В листинге 7 приведен пример файла /boot/grub/grub.conf, с помощью которого мы и разберем приемы настройки GRUB.

Листинг 7. Пример файла /boot/grub/grub.conf

default=0
timeout=10
splashimage=/grub/splash.xpm.gz

title ASPLinux-2.6.14
	kernel /vmlinuz-2.6.14-1.1653.1asp root=/dev/hda3  reboot=b pci=noacpi pci=usepirqmask quiet rhgb resume=/dev/hda1 
	initrd /initrd-2.6.14-1.1653.1asp.img
	boot
	root (hd0,1)
	setup (hd0)

title Windows
	map (hd0,0) (hd0,2)
	map (hd0,2) (hd0,0)
	rootnoverify (hd0,2)
	chainloader +1

Вначале обратите внимание на две секции этого файла, начинающиеся со слова "title". Каждая из этих секций предназначена для организации загрузки какой-то из операционных систем, имеющихся на ваших дисках. После слова "title" (в той же строке) стоит название этого варианта (вы можете задать его произвольным образом). Эти названия появятся в виде пунктов меню загрузки.

Вначале рассмотрим первую из этих секций, которая обеспечивает загрузку Linux. Строка этой секции, начинающася со слова "root", указывает, какой раздел и на каком диске содержит образ ядра Linux (это может быть как корневой раздел файловой системы Linux, так и любой другой раздел или диск). В нашем случае строка "root (hd0,1)" сообщает GRUB, что файл ядра находится на втором разделе диска /dev/hda. Еще раз обратите внимание на систему именования дисков в GRUB, в которой числа 0-3 используются для обозначения первичных разделов диска, а числа с 4 и больше - для обозначения логических разделов. В данном случае применяется именование дисков способом, принятым в GRUB.

Все ссылки на каталоги и файлы, встречающиеся далее в той же секции конфигурационного файла, являются относительными к разделу, указанному строкой "root (hd0,1)". Поэтому не стоит удивляться, когда в строке, начинающейся словом "kernel" (эта строка сообщает GRUB, где находится ядро) записано
kernel /vmlinuz-2.6.14-1.1653.1asp
хотя в работающей системе вы найдете файл ядра в каталоге "/boot". Просто эти строки могут иметь различный вид в зависимости от того, имеется или нет у вас отдельный раздел для каталога /boot. В моем случае каталог "boot" вынесен в отдельный раздел. Поэтому образ ядра расположен в корне этого раздела. То же самое относится и к строке "initrd", которая содержит указание на местоположение файла образа виртуального диска.

Кроме местоположения ядра в строке, начинающейся словом "kernel", заданы некоторые параметры начальной загрузки, о которых мы поговорим в следующем разделе. Пока что обратите внимание на параметр "root=", имеющийся в этой строке. Как мы увидим ниже, этот параметр задает местоположение коневой файловой системы Linux. В отличие от команды "root (hd0,1)" конфигурационного файла здесь уже используется метод именования дисков, принятый в Linux.

Секция, обеспечивающая загрузку Windows, нас не очень интересует, поэтому скажем о ней очень кратко. Строки, начинающиеся словом "map", в секции, задающей загрузку Windows 98, заставляют Windows полагать, что она установлена в первый раздел первого диска. Строка "rootnoverify" сообщает GRUB, что требуется загрузить систему с Windows-раздела, не пытаясь его смонтировать, а строка "chainloader +1" требует от GRUB передать управление загрузчику Windows.

Теперь давайте вернемся к началу конфигурационного файла, где находятся несколько строк (в примере их 3), которые определяют поведение GRUB на этапе выдачи пользователю начального меню загрузки. Эти строки можно назвать секцией глобальных настроек, как это было в случае с LILO.

Команда "default=0" в этой секции определяет вариант загрузки, выбираемый по умолчанию, то есть в том случае, когда пользователь не выбрал (с помощью клавиатуры) какой-то другой вариант. Возможные варианты задаются секциями title (смотри выше), причем нумерация начинается с нуля. В примере из листинга 7 имеются только две секции "title" и, следовательно, возможны только два варианта загрузки по умолчанию - "default=0" и "default=1".

Команда "timeout=10" определяет период времени (в секундах) в течение которого GRUB ожидает, пока пользователь выберет нужный вариант загрузки, введет дополнительные команды или задаст нужные параметры загрузки. Если по истечении этого времени пользователь не нажал ни одной клавиши, будет автоматически выбран вариант загрузки, определяемый командой "default=n".

Число различных параметров, которые можно задать в конфигурационном файле GRUB, довольно велико, так что приводить здесь описания каждого из них не имеется возможности. Тем более, что необходимые сведения можно легко найти в многочисленных статьях, доступных в Интернет (смотри, например, статьи [19-31]). Кроме того, самое полное руководство по GRUB (но на английском языке) вы найдете на сайте GNU.ORG (см. [32-34]). Отметим только еще раз, что в отличие от LILO, GRUB не требует переустановки после внесения изменений в свой конфигурационный файл.

Как происходит загрузка с GRUB

При инсталляции GRUB полуторный загрузчик из файла fsname_stage1_5 (естественно, соответствующий файловой системе диска) записывается в последовательные сектора жесткого диска, следующие за загрузочным сектором на нулевой дорожке диска. Размер этой области (в байтах) равен числу секторов на дорожке минус 1, умноженному на 512, но полуторный загрузчик достаточно мал (посмотрите размер файла fsname_stage1_5 на своем диске), чтобы здесь разместиться.

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

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

Прежде чем перейти к этапу загрузки ядра Linux, надо сказать несколько слов о параметрах начальной загрузки, которые могут быть переданы загрузчику, а через него - ядру и процессу init.


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