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

UnixForum






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

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

На главную -> MyLDP -> Тематический каталог -> Процесс начальной загрузки системы

GRUB... действительно - GRand!


Автор: Владимир Попов, popov_inm@yahoo.com
Опубликовано: 30.01.2002
Оригинал: http://www.softerra.ru/freeos/15595/


"Существование" любой вычислительной системы представляет собой процесс последовательного выполнения главным вычислительным узлом (в миру - CPU) инструкций (операторов). И, как процесс "последовательный", он должен как-то начинаться. Со времен первых ЭВМ для определения этого начала используют специальное слово "boot", общепринятый русский перевод которого - "начальная загрузка", "загрузить". Спросите, зачем так "издалека"? А затем, что большинство пользователей никогда не задумывалось над тем, что представляют собой эти самые boot loader-ы (первичные загрузчики). Общепринятым заблуждением является то, что загрузчик - часть ОС, что, в принципе, не верно, хотя создаются они, как и любое другое ПО, в рамках той или иной операционной системы и ориентированы, обычно, на выполнение загрузки в первую очередь этой самой "материнской" ОС. Но "обычно" не означает "всегда". Прежде всего, это не относится к вычислительным системам, не использующим операционную систему вообще: многие однокристальные ЭВМ и все устройства на их основе, конечные автоматы и т.п. Эти системы не являются предметом нашего рассмотрения и упомянуты только для того, что бы проиллюстрировать, что загрузка (boot) - общее свойство вычислительных систем, а старт операционной системы IBM PC - частный случай загрузки. Возможно, в таком взгляде на IBM PC есть своя логика. Во всяком случае, Erich Boleyn, первый разработчик GRUB, по роду своей основной деятельности имел дело прежде всего с вычислительными устройствами, обеспечивающими высокоскоростную передачу в сетях, и только потом - с IBM PC.

Прежде чем продолжить рассказ о GRand Unified Bootloader-е (именно из этих трех слов составлена аббревиатура GRUB), несколько слов о том, для кого это может быть интересно. Если Вы используете ОДНУ операционную систему ОДНОГО производителя (хотите, угадаю - какого?), то Вам это не нужно. Во всех остальных случаях - может пригодиться. Хотите иметь несколько win'9x на одном диске? Вообще, несколько разных операционных систем? Загрузку с любого из физических дисков (без выхода в BIOS Setup)? Универсальную загрузочную дискету? Попробовать альтернативу LILO? Если хотя бы один из ответов был положительным - читайте дальше.

Итак, дальнейшее уже будет иметь отношение исключительно к IBM PC. Архитектура этого, без сомнения, самого многочисленного клона компьютеров предполагает загрузку в ОЗУ с нулевого адреса так называемой MBR (Master Boot Record) - первого (или нулевого, в зависимости от того, с чего начинать считать) блока загрузочного устройства, и передачу на него управления. Загрузочными устройствами могут быть FDD, HDD или CD ROM, определяется это обычно в BIOS Setup. Во всех случаях размер MBR - 512 байт. Для MBR жесткого диска стандартизированы также возможное количество разделов (четыре, причем только один - расширенный (extended), который может содержать логические диски), структура и местоположение Partition Table - таблицы разделов, описывающей их геометрию, тип файловой системы и признаки активности (загружаемости). Стандарт этот можно бы и игнорировать, но тогда никакое "чужеродное" ПО не сможет определить содержит ли диск хоть что-нибудь разумное. Поэтому и не игнорируют - даже MicroSoft, упорно "не замечающая" возможности существования нескольких первичных разделов. А вот содержимое MBR от "0" до Partition Table - не регламентировано. То есть, как раз исполняемые инструкции могут быть различными. И имеется под них всего-то 384 байта. Трудно разместить в таком объеме что-либо существенное - вместо этого размещают код очередного (в смысле очередности этапов загрузки) loader-a. В простейшем случае этот загрузчик загружает (уж простите за тавтологию) в память содержимое начального блока одного из primary (первичных), активного (bootable) раздела. Этот начальный блок, в отличие от начального блока диска называется уже не Master..., а просто - Boot Record). Так это делалось от MS DOS вплоть до win'9x. В более сложных случаях инструкции, считанные из MBR, служат для того, что бы загрузить первичный загрузчик ОС, будь то NTLoader, LILO и т.п. Такой специальный загрузчик нужен для многих целей: во-первых, сама загрузка ОС может быть достаточно сложной, чтобы не "умещаться" в одном блоке; во-вторых, сколько-нибудь серьезная система предполагает возможность загрузки нескольких ядер (в простейшем случае хотя бы один дополнительный, аварийный (failsave) вариант); в-третьих, "хорошим тоном" считается сохранение возможности загрузки предыдущей версии ОС; ну и в-четвертых, хорошо бы предоставить пользователю возможность использовать еще одну ОС, хотя и не все производители ПО так считают. Уже вышеприведенное описание показывает, что есть два принципиально различных способа загрузки. Первый - "тупой" или, выражаясь мягче, "аппаратный" - так называемая загрузка "цепочкой": последовательная загрузка начальных блоков сначала диска в целом, а затем - активного раздела. Недостатком этого способа являются архитектурные ограничения (не более четырех первичных разделов), и трудность размещения в одном блоке (512 байт) более-менее сложного ПО, обеспечивающего, например, начальный диалог с пользователем. Альтернатива - "интеллектуальный" способ, предполагающий наличие специальной программы, имеющей доступ к файлам, расположенным на диске. Этот доступ позволяет вынести содержание и алгоритм работы меню загрузки в файлы, редактируемые пользователем, снимает все возможные ограничения на количество загружаемых систем или ядер одной и той же системы. Именно по этому пути и пошли разработчики всех современных менеджеров загрузки (из уважения, по-видимому, программы этого класса именуют уже не загрузчиками, а менеджерами).
Последний комментарий по поводу соотношения загрузчиков и ОС. Загрузчик не является частью ОС, поскольку не использует ее ресурсы (не может пока: ОС-то еще не загружена). Загрузчик зависим от ОС настолько, насколько его файлы "привязаны" к файловой системе данной ОС. Чем больше количество файловых систем, на которых могут находиться файлы загрузчика, тем больше его "вне-системность".

Обойдя ограничение четырех первичных разделов и невозможности загрузки разделов логических, разработчики менеджеров загрузки столкнулись с очередной трудностью - особенностями файловых систем, которые теперь уже были "небезразличны", и особенностями загрузки ядер различных ОС. Что касается файловых систем, то с этим "разобрались" быстро. Так, в исполнении авторов GRUB, программный "слой", обеспечивающий доступность файлов на томах 6-ти различных систем "уместился" в 6-ти файлах общим объемом чуть более 45-ти кбайт. А вот что касается загрузки ядер, то тут ожидать "консенсуса" не приходится. Но, на самом деле, такая цель и не ставилась.
В 1995 году, ядро Hurd (оригинальная ОС, включающая в себя множество инноваций, обсуждение которой выходит далеко за рамки данной статьи) достигло "готовности", когда нужно было уже задуматься о способе его загрузки. Вышеупомянутый Erich Boleyn в соавторстве с Brian Ford не стал "умножать" количество мало совместимых способов загрузки IBM PC, предложив вместо этого Multiboot Specification - спецификацию, обеспечивающую универсальный способ загрузки ядер ОС. Вряд ли молодые люди рассчитывали на то, что, например, MicroSoft Co. приведет загрузку Windows XP к упомянутой спецификации, но для ядер Hurd, FreeBSD, NetBSD, OpenBSD и Linux мы получили действительно унифицированный подход. Приверженцам MicroSoft расстраиваться не пришлось: загрузка систем и загрузчиков, не совместимых с Multiboot Specification возможна по алгоритму "цепочки". Собственно говоря, все ОС MicroSoft, кроме NT, только так и загружались. Что же касается NT, то по "цепочке" загружается NTLoader, выполняя после своей загрузки все возложенные на него функции. Дальше - больше. В 1999 году Gordon Matzigkeit и OKUJI Yoshinori представили GRUB как официальный пакет GNU. Круг участников проекта расширился, а функциональность пакета еще более возросла. Кроме изначально присущих уникальных возможностей, ориентированных, в основном, на разработчиков ядер ОС (и, как следствие, мало понятных большинству рядовых пользователей), на настоящий момент GRUB:

  • принимает практически все форматы исполнимых файлов;
  • обеспечивает загрузку ядер, совместимых и ограниченно совместимых со спецификацией Multiboot;
  • поддерживает "цепочный" механизм для ОС и загрузчиков, не совместимых со спецификацией Multiboot;
  • поддерживает загружаемые модули;
  • поддерживает редактируемый текстовый конфигурационный файл;
  • имеет меню-ориентированный и гибкий командный интерфейсы, удовлетворяющие, практически, любым запросам пользователя;
  • поддерживает файловые системы: BSD FFS, DOS FAT16 и FAT32, Minix fs, Linux ext2fs, ReiserFS, и VSTa fs;
  • обеспечивает автоматическую декомпрессию gzip-файлов;
  • независим от геометрии дисков: переход к диску с другой трансляцией номеров блоков не потребует изменения конфигурации;
  • определяет LBA-режим: если BIOS поддерживает LBA, GRUB пользуется этой поддержкой;
  • поддерживает сетевую загрузку по TFTP-протоколу;
  • поддерживает терминальный доступ по последовательному интерфейсу, т.е. может использоваться в без-консольных станциях.

Согласитесь: приведенный список - веская заявка на титул "GRand". Присмотримся поближе. Поскольку проект выполняется в рамках GNU, то информация о нем находится на http://www.gnu.org/software/grub/. Продукт и в настоящее время в стадии "alpha" (не пугайтесь, это определяется больше уровнем притязаний разработчиков, нежели работоспособностью уже сделанного), поэтому загрузить его можно только с ftp://alpha.gnu.org/gnu/grub/. Там находится три файла. На декабрь 2001-го это:
grub-0.90.tar.gz - архив исходников, достаточных для построения GRUB в любой ОС клона unix;
grub-0.90-i386-pc.ext2fs - образ загружаемой дискеты со всеми необходимыми файлами;
grub-0.90-i386-pc.tar.gz - архив бинарных файлов, достаточных для загрузки (но не для инсталляции) в любой из поддерживаемых файловых систем.
Версия со временем, разумеется, изменится, но подход, будем надеяться, останется прежним.

Для unix систем, безусловно, нужно использовать первый архив. Выполнив стандартные для unix configure-make-make check-make install, получаем три исполняемых файла в .../sbin, три man-страницы в .../man/man8, исчерпывающее info в .../info и восемь бинарных файлов в .../share/grub/i386-pc, образующих в разных комбинациях собственно bootloader. Добавлять что-либо к info нет необходимости, но все это - только для unix. А где же "мультисистемность"? Оказывается - есть. Для инсталляции GRUB в любой из файловых систем на жестком или флоппи-диске нужно создать в корне этой файловой системы каталог /boot/grub (различия между прямым и обратным слэшем нивелируются) и перенести в него несколько файлов из архива grub-0.90-i386-pc.tar.gz: stage1 и stage2 - обязательно, а файлы с постфиксом stage1_5 - только те, которые обеспечат GRUB доступ к нужным файловым системам (которые - очевидно из их названий). Собственно инсталляцию, то есть запись кода загрузчика в MBR, выполнить тоже можно, но не нужно: разумнее последовать рекомендации авторов и выполнить инсталляцию непосредственно из grub, запущенного, например, с дискеты, созданной из grub-0.90-i386-pc.ext2fs. Под unix такая дискета делается командой:
dd if=./grub-0.90-i386-pc.ext2fs of=/dev/fd0
под DOS - с помощью известной утилиты rawrite.
под win - rawwrite

Загрузившись с дискеты, знакомимся с тем самым "гибким командным интерфейсом". Пользователи unix удивлены не будут: очень похоже на bash, остальным же, возможно, будет интересно познакомиться с памятью команд и авто-заполнением. Диалог начинается выводом перечня допустимых команд. Информацию по любой из команд можно получить, набрав help <имя команды>. В простейшем случае, для инсталляции GRUB потребуется всего две команды: root (hdn,m) и setup (hd0). Первая из команд указывает, где искать каталог /boot/grub с находящимися в нем файлами *stage*. Имя устройства всегда заключается в круглые скобки. n - номер диска, m - номер раздела Способ обозначения разделов аналогичен принятому в unix (только нумерация начинается не с единицы, а с нуля), но для пользователей других систем может показаться "неочевидным". На помощь придет авто заполнение команды: табуляция после root ( - выведет список допустимых устройств. Еще одна табуляция - и на экране список всех разделов выбранного диска. Может оказаться полезной команда find /boot/grub/stage1 - она-то уж точно укажет номер раздела, где создан искомый каталог. С помощью этой же команды можно искать любой файл на всех разделах диска и дискете. Не забывайте только, что path в данном случае - обязательный компонент имени. Поэтому, если файл должен быть в корневом каталоге раздела, не забудьте прямой слэш перед именем. Команда setup выполнит все необходимые для инсталляции действия. В качестве параметра - диск, с которого и будет происходить загрузка. Однако с setup можно и не торопиться. Почему бы не проверить себя еще раз? Для этого команды загрузки ОС вводятся непосредственно в командном режиме (впоследствии эти команды составят конфигурационный файл).
Для Linux это, например:
kernel (hd0,6)/boot/vmlinuz-up root=/dev/hda7
Команда загружает ядро, расположенное на третьем логическом диске расширенного раздела.

для win'98:
makeactive
chainloader +1
Первая команда делает активным (загружаемым) раздел, выбранный командой root, вторая - загружает в память начальный загрузчик этого раздела.
Команда boot передает управление загруженным ядру или загрузчику.
Если все в порядке - возвращаемся к setup и заканчиваем инсталляцию.

Вообще, перечень доступных команд достаточно обширен и всегда может быть выведен на экран нажатием <TAB>. Кроме команд, использование которых предполагает наличие специальных знаний (blocklist, debug, displayapm, displaymem, impsprobe, ioprobe, read, serial, setkey, terminal, testload, uppermem), имеются следующие группы команд:

  • управления:
    • boot - передать управление ядру, загруженному командой kernel или "чужому" загрузчику, загруженному командой chainloader,
    • halt - выключить машину,
    • help [команда] - выдать подсказку,
    • quit - выйти из GRUB,
    • reboot - перезагрузиться,
    • pause - ждать нажатия клавиши;
  • работы с файлами:
    • cat - вывести на экран,
    • cmp - сравнить содержимое двух файлов;
  • управления доступом:
    • password - обычно помещается в конфигурационном файле и при достижении ее требует ввода пароля,
    • lock - блокировать выполнение команд для неидентифицированного пользователя;
  • модификации разделов:
    • partnew - создать первичный раздел,
    • partype - изменить тип раздела;
  • настройки внешнего вида:
    • color - задать цвета меню,
    • vbeprobe - определить и вывести доступные режимы видеоадаптера,
    • testvbe MODE - тестировать режим MODE видеоадаптера.

Приведенный список команд не полон, но более подробное обсуждение было бы слишком объемным, тогда как еще не рассмотрены команды, с помощью которых, собственно, и выполняются варианты загрузки. Эти же команды являются основным содержанием конфигурационного файла. Файл этот называется menu.lst и располагается все в том же /boot/grub. В начале файла обычно размещаются команды задания цветов:
color light-gray/blue black/light-gray
первая пара цветов определяет основной и фоновый цвета для "не выбранных" позиций меню, вторая - для "выбранных".

Время (в секундах) от момента вывода меню до выполнения позиции, определенной, как "умолчание", задается командой:
timeout 10

Позиция "по умолчанию" задается, как:
default 0

Если загрузка "по умолчанию" по какой-либо причине не возможна, то будет предпринята попытка выполнить позицию, указанную в команде:
fallback 1

Цифры, определяющие позицию меню, могут быть, разумеется, любыми. Обратите внимание только на нумерацию - с нуля.

Описание каждой из позиций меню начинается с команды:
title text
где text - остаток строки от первого "непробельного" символа после title.

Группа команд одной позиции меню в обязательном порядке имеет уже упомянутую команду root. ОС, хотя бы частично соответствующие Multiboot Specification, загружаются командой kernel, причем в строке можно указывать дополнительные параметры. Так, команда
kernel (hd0,6)/boot/vmlinuz-up root=/dev/hda7 hdd=ide-scsi vga=788
загрузит Linux, корневым каталогом назначит /dev/hda7, включит эмуляцию ide-scsi, нужную для пишущего привода CD и переведет видеоадаптер в режим 800х600 графической консоли, для работы с так называемым frame buffer device (спасибо Алексею Федорчуку - я и не знал, что это так называется).

Для ОС, не соответствующих Multiboot Specification, сначала взводится бит "активности" раздела, выбранного командой root:
makeactive
а, затем, методом "цепочки" загружается собственный загрузчик данной ОС:
chainloader +1

Поскольку ОС семейства win'9x не могут быть загружены из соседних разделов (вне зависимости от флага активности грузится все равно первый из разделов), для их загрузки нужно использовать команды hide и unhide. Так, если первый и второй первичные разделы содержат win'9x, то для загрузки второй системы нужно включить в menu.lst следующие команды:
hide (hd0,0)
unhide (hd0,1)
root (hd0,1)
makeactive
chainloader +1

Аргументы hide, unhide и root для загрузки первой системы, думаю - очевидны.

Еще одна трудность с ОС от MicroSoft - неспособность грузиться со второго и последующих дисков. Для ее преодоления применяют технику "свопирования" (swapping technique), или, проще - "подмены".
Так же, собственно, поступает и BIOS Setup, но зачем же обращаться к нему, если всего две строки в menu.lst выполнят ту же операцию:
map (hd0) (hd1)
map (hd1) (hd0)

Во всех случаях не лишним будет сначала загрузиться с дискеты, запустить grub и проверить, соответствует ли результат выбранных команд ожидаемому. В командном режиме существует специальная команда, загружающая созданный menu-файл:
configfile FILE

Еще один совет - для начала инсталлировать GRUB на дискете. Скорость загрузки с дискеты радует, что, собственно, и не удивительно: общий объем загружаемых файлов - менее 100 кбайт.

Ну, и последняя рекомендация, содержащаяся в инструкциях абсолютно ко всем менеджерам загрузки: до инсталляции нового менеджера загрузки сохраните MBR! В unix это можно сделать командой:
dd if=/dev/hd0 of=your_file bs=512 count=1
в DOS - с помощью NortonDiskDoctor, например.

Сравнительный анализ различных менеджеров загрузки выходит за рамки данной статьи, но даже без такого анализа можно, наверное, согласиться, что "GRand" - вполне заслуженный титул для рассматриваемого пакета. GRUB - даже больше, чем "unified bootloader". Дискета с ним позволит проанализировать разделы потерявшего способность к загрузке винчестера, загрузить любой из первичных разделов или любое из ядер Hurd, FreeBSD, NetBSD, OpenBSD или Linux. Возможно и более "изощренное" вмешательство в структуру разделов диска, но это, пожалуй, уже другая тема.