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

UnixForum






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

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

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

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


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

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

Рассмотрение файла System.map увело нас немного в сторону от основной цели. Давайте вернемся к исследованию процедуры загрузки Linux. На очереди у нас действия, выполняемые загрузчиком второго этапа. Как было сказано в разделе 3.2, основная задача загрузчика второго этапа состоит в том, чтобы перенести в оперативную память образ ядра и образ виртуального диска initrd и передать управление ядру. Посмотрим, как это делают два основных загрузчика, используемых в настоящее время в Linux, и как на действия загрузчика может повлиять пользователь или администратор системы. Начнем с традиционого LILO.

3.4. Загрузчик LILO

Загрузчик LILO (от LInux LOader), разработанный Вернером Алмесбергером (Werner Almesberger), долгое время был основным загрузчиком в большинстве дистрибутивов Linux. И хотя в последнее время все больше дистрибутивов переходят на использование загрузчика GRUB, у Lilo остается немало приверженцев. Дистрибутив Slackware 12, например, даже не предлагает выбора между LILO и GRUB в процессе инсталляции: только LILO.

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

3.4.1. Устройство LILO

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

  • собственно загрузчик — это та часть LILO, которая первой загружается в память через прерывание BIOS, и которая загружает ядро Linux (или загрузочный сектор другой операционной системы). Загрузчик тоже состоит из двух частей. Первая часть, - первичный загрузчик, - записывается в загрузочный сектор и служит для загрузки второй части, которая значительно больше по размеру. Обе части обычно хранятся на диске в файле /boot/boot.b.
  • программа /sbin/lilo, которая запускается из-под Linux, является, фактически, программой установки LILO, служит для того, чтобы записать в соответствующие места всю информацию, необходимую на этапе загрузки. Ее необходимо перезапускать каждый раз после внесения изменений в ядро или в конфигурационный файл LILO;
  • различные служебные файлы, которые нужны LILO во время загрузки. Эти файлы обычно располагаются в каталоге /boot. Самый важный из них — это map-файл (/boot/map), в котором указывается местоположение ядра;
  • еще один важный файл — это файл конфигурации LILO, который обычно имеет имя /etc/lilo.conf.

Кроме того, LILO во время загрузки нужны еще следующие файлы:

  • все загружаемые версии ядра (если вы выбираете версию ядра на этапе загрузки);
  • загрузочные сектора других операционных систем, которые будут загружаться через LILO;
  • сообщения, выдаваемые при загрузке (если таковые определены).

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

  • загрузочный сектор дискеты в формате Linux (/dev/fd0, ...);
  • MBR первого жесткого диска (/dev/hda, /dev/sda, ...);
  • загрузочный сектор первичного раздела файловой системы Linux на первом жестком диске (/dev/hda1, /dev/hda2, ...);
  • загрузочный сектор логического раздела в расширенном разделе первого жесткого диска (/dev/hda5, ...). Правда большинство программ типа fdisk не предполагают, что можно загружаться из расширенного раздела и отказываются объявлять его активным. Поэтому в состав LILO включена специальная программа (activate), которая позволяет обойти это ограничение. Но программа fdisk из дистрибутива Linux поддерживает возможность активизации расширенного раздела. Для этого надо использовать либо опцию -b, либо переменную BOOT.

Первичный загрузчик LILO не может быть размещен в следующих местах:

  • загрузочный сектор дискеты или первичного раздела, отформатированных в других файловых системах;
  • в swap-разделе Linux;
  • на втором жестком диске.

Если первичный загрузчик от LILO установлен в главный загрузочный сектор, он загружается системным BIOS в оперативную память по адресу 0х7C00 и ему передается управление. Затем первичный загрузчик, снова используя системный BIOS, загружает в память вторичный загрузчик по адресу 0x9B000.

3.4.2. Конфигурирование LILO

Большая часть настроек LILO может быть выполнена путем редактирования используемого по умолчанию файла конфигурации, каковым является файл /etc/lilo.conf.

Файл lilo.conf состоит из двух секций - секции глобальных настроек и секции локальных настроек. Секция локальных настроек разделена, в свою очередь на подсекции, по одной для каждого из возможных вариантов загрузки. Вот небольшой пример файла lilo.conf :

Листинг 6. Пример файла /etc/lilo.conf

   # Секция глобальных настроек
   #
   boot=/dev/hda
   linear
   compact
   read-only
   prompt
   timeout=100
   vga = normal
   # message = /boot/bootmesg.txt
   
   # Секция локальных настроек
   #
   # Подсекция 1
   #
   image = /boot/vmlinuz-2.6.14
     root = /dev/hda1
     label = vmlinuz-2.6.14
   #
   # Подсекция 2
   #
   image = /boot/vmlinuz-2.6.13
     root = /dev/hda1
     label = vmlinuz-2.6.13

Рассмотрим вначале секцию глобальных настроек. Первая строка в этой секции указывает, где будет установлен LILO. В нашем примере LILO будет установлен в главный загрузочный сектор первого жесткого IDE-диска, обозначаемого как /dev/hda.

Вторая строка (linear) означает, что LILO должен использовать не обычную адресацию диска цилиндр/головка/сектор, а линейную адресацию секторов. Эта опция несовместима с вариантом загрузки системы с дискеты, но необходима для некоторых SCSI-контроллеров, а также в случае расположения ядра выше 1024-го цилиндра.

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

Четвертая строка (read-only) сообщает LILO, что корневая файловая система должна быть смонтирована в режиме "только для чтения". Стартовые скрипты, запускаемые процессом init, позже перемонтируют корневую файловую систему в режим "чтение-запись" (после того, как эта система будет проверена командой fsck).

Пятая строка требует, чтобы LILO перед загрузкой какой-либо версии ядра, выдал пользователю приглашение. Если эта строка отсутствует, LILO автоматически загрузит ядро, указанное по умолчанию. Если опция prompt задана, но интервал задержки (опция timeout) не указана, то перезагрузка без участия пользователя будет невозможна, поскольку LILO будет бесконечно ждать, пока пользователь не введет что-либо.

Шестая команда в секции глобальных настроек (timeout=100) сообщает LILO длительность интервала, в течение которого LILO должен ждать реакции пользователя, после чего можно (или нужно) загрузить ядро по умолчанию. Единицей измерения времени тут служит одна десятая секунды, так что timeout=100 задает интервал в 10 секунд.

С помощью команды message можно заставить загрузчик выдавать при загрузке произвольное сообщение.

Теперь давайте рассмотрим секцию локальных настроек файла lilo.conf. Эта секция может содержать несколько подсекций, каждая из которых начинается ключевым словом image или other. Та из этих подсекций, которая стоит в файле первой, определяет ядро, загружаемое по умолчанию. Можно указать загружаемую по умолчанию систему с помощью строки вида default=vmlinux-2.6.14 (используя метку из соответствующей строки label). Строка, начинающаяся ключевым словом image, содержит полный путь к файлу ядра, загружаемого при выборе этой подсекции.

LILO может загружать различные операционные системы, каждая из которых, как правило, размещается в отдельном разделе жесткого диска. Даже если известен полный путь к ядру, которое будет загружаться, LILO должен знать в каком разделе жесткого диска размещается каталог /boot с образами ядра. Этот раздел указывается в строке, обозначенной ключевым словом root. Другими словами, опция root в каждой подсекции сообщает LILO, какой раздел диска монтировать как корневую файловую систему. Таким образом, при обработке секции:

   image = /boot/vmlinuz-2.6.14
     root = /dev/hdb1
     label = vmlinuz-2.6.14
LILO будет искать ядро /boot/vmlinuz-2.6.14 на первом разделе второго жесткого диска (slave на первом IDE-контроллере), а при обработке секции
   image = /boot/vmlinuz-2.6.13
     root = /dev/hdb2
     label = vmlinuz-2.6.13

LILO будет искать ядро /boot/vmlinuz-2.6.13 на втором разделе того же диска.

Наконец, ключевое слово label задает просто название подсекции или варианта загрузки. Именно эти названия выдаются после нажатия клавиши <TAB> при появлении приглашения LILO. Одно из этих названий вы должны ввести в ответ на приглашение, чтобы загрузилось нужное вам ядро. Две разных подсекции не должны иметь одинаковых названий, иначе lilo может заартачиться.

3.4.3. Запуск операционных систем, отличных от Linux

Для загрузки операционных систем, отличных от Linux, служат секции конфигурационного файла, обозначаемые ключевым словом other. В простейшем случае такая секция может иметь вид:
   other = /dev/hda4
     label = win95
     table = /dev/hda

Ключевое сллово other в данном случае выполняет ту же роль, какую в предыдущих случаях выполняло слово root, то есть оно указывает, где располагается загрузочный раздел данной операционной системы. В нашем примере это четвертый раздел первого IDE-диска. Ключевое слово label, как и в предыдущем случае, задает только название, которое будет выводиться в соответствующей строке меню. Table показывает, где расположена таблица разбиения соответствующего диска. В этой строке всегда указывается диск, который содержит альтернативную ОС, причем имя задается в нотации, принятой в Linux (то есть - /dev/hda, /dev/hdb, /dev/hdc, /dev/sda и т.д.).

3.4.4. Замечания о безопасности

В целях безопасности имеет смысл сделать файл /etc/lilo.conf принадлежащим пользователю root и группе root, а также задать права доступа равные 600:
	# ll /etc/lilo.conf
	-rw-------   1 root     root          500 Jan 21 00:03 /etc/lilo.conf
Если вы делаете резервные копии основных конфигурационных файлов вашей системы, имеет смысл включить в число таких файлов и файл /etc/lilo.conf.
Если вы добавите в подсекцию команду password, вторичный загрузчик перед загрузкой ядра, указанного в данной подсекции, запросит у вас пароль. Если дополнительно указать опцию restricted, пароль будет запрашиваться только если в командной строке будут заданы еще какие-то опции, например, опция `single', переводящая Linux в однопользовательский режим. Вот пример подсекции, защищенной паролем:
   image = /boot/vmlinuz-secret
     label = secret_kernel
     root = /dev/hda3
     password = mypassword
     restricted
Только не надо заблуждаться относительно надежности защиты таким паролем. Он далеко не обеспечивает безопасность вашей системы. Любой человек, получивший физический доступ к компьютеру, может загрузиться с дискеты, установить собственную версию LILO и получить доступ к системе в режиме суперпользователя.

3.4.5. Установка загрузчика

После внесения каких-либо изменений в файл конфигурации необходимо выполнить команду lilo (исполняемый файл lilo расположен в каталоге /sbin) для того, чтобы сделанные изменения вступили в силу. Эта команда (которая в руководстве по LILO называется map-installer) перезаписывает загрузочный сектор, устанавливает вторичный загрузчик системы, который будет активизирован во время следующей загрузки машины, и соответствующим образом изменяет map-файл. Прежде, чем запускать /sbin/lilo для модификации загрузочных процедур, выполните эту команду с параметром -t. При этом будет выполнена вся процедура инсталляции загрузчика, кроме изменения map-файла, записи модифицированного загрузочного сектора и изменения таблицы разбиения диска, то есть выполнен тест нового варианта. Если добавить еще опцию -v, вы получите более подробную информацию о том, что будет делать команда /sbin/lilo.

После этого можно выполнить команду /sbin/lilo уже без параметров, чтобы произвести запись изменений на диск. При этом будет снова зачитан файл настроек /etc/lilo.conf и произойдет запись новой конфигурации загрузчика на жесткий диск. Если сделанные вами изменения не имеют явных погрешностей, вы увидите сообщение, подобное приведенному ниже:

	Added vmlinux-2.6.14 *
	Added vmlinuz-2.6.14-my
	Added vmlinux-2.6.13
Звездочка указывает на ядро, загружаемое по умолчанию.

Если такого сообщения не появилось, то скорее всего будет выдано сообщение об ошибке. Приведу несколько примеров таких сообщений (обратите внимание на то, что это ошибки, возникающие на этапе выпонения команды /etc/lilo, а не на этапе загрузки системы):

  • geo_comp_addr: Cylinder number is too big (5064 > 1023)
    Одно из ваших ядер расположено далее 1024-го цилиндра. В таком случае вы можете попытаться добавить опцию linear в секцию глобальных настроек файла /etc/lilo.conf.
  • open /boot/vnlinuz-xxx: No such file or directory
    Отсутствует ядро, указаное в секции image.
  • Label "a_very_long_label_which_lilo_cant_use" is too long
    Вы выбрали слишком длинное имя для метки. Сократите название секции.

Когда /sbin/lilo перезаписывает загрузочный сектор, старое содержимое этого сектора автоматически сохраняется в файле. По умолчанию это файл /boot/boot.NNNN, где NNNN соответствует номеру устройства, например, 0300 — это /dev/hda, 0800 — это /dev/sda и т. д. Если такой файл уже существует, он не перезаписывается. Но можно задать альтернативный файл для сохранения загрузочного сектора.

Файл /boot/boot.NNNN можно использовать для восстановления старого содержимого загрузочного сектора, если более простой метод его восстановления недоступен. Соответствующие команды имеют вид:

[root:~#] dd if=/boot/boot.0300 of=/dev/hda bs=446 count=1

или

[root:~#] dd if=/boot/boot.0800 of=/dev/sda bs=446 count=1

(bs=446 потому что восстанавливаем только программу-загрузчик, и не трогаем таблицу разбиения диска).

Копию загрузочного сектора лучше сохранить на дискете. В случае, если произойдут какие-либо неприятности, вы сможете восстановить старую загрузочную запись MBR, выполнив команду (предполагается, что дискета смонтирована в каталог /mnt):

[root:~#] dd if=/mnt/MBR of=/dev/hda bs=446 count=1

Восстановить старый MBR при необходимости можно также командой /sbin/lilo с опцией -u. Только надо иметь в виду, что эта команда отрабатывает корректно при условии, что каталог LILO (а именно, /boot) не изменялся со времени инсталляции.

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

3.4.6. Сообщения об ошибках на этапе загрузки LILO

Когда LILO загружается, он выводит на дисплей слово "LILO". При этом вывод каждой буквы обозначает завершение определенного действия или этапа загрузки LILO. Если загрузка сорвется, то по числу выведенных букв можно судить о причине возникновения проблемы.

  • Ничего не выведено — никакая часть LILO не была загружена. Либо LILO не был установлен, либо раздел, на котором он находится, не является активным.
  • L [код ошибки] — первичный загрузчик загрузился и стартовал (на него передано управление), но он не сумел загрузить вторичный загрузчик. Двухзначный код ошибки указывает на конкретную причину проблемы (расшифровку кодов надо искать в технической документации на LILO). Обычно это связано с дефектами носителя или неправильно заданной геометрией диска. Если только LILO не остановился на этом этапе, выдавая бесконечную последовательность кодов ошибки, проблема обычно легко решаема.
  • LI — первичный загрузчик сумел загрузить вторичный загрузчик, но не сумел запустить его на выполнение. Это может быть вызвано ошибкой в задании геометрии диска или тем, файл /boot/boot.b был перемещен без перезапуска /sbin/lilo.
  • LIL — вторичный загрузчик запустился, но не смог загрузить таблицу дескрипторов из map-файла. Причина обычно состоит в наличии дефектов на диске или неправильно заданной геометрией диска.
  • LIL? — вторичный загрузчик был загружен по неправильному адресу. Обычно вызвано ошибкой в задании геометрии диска или тем, что файл /boot/boot.b был перемещен без перезапуска /sbin/lilo.
  • LIL- — таблица дескрипторов разрушена. Обычно вызвано ошибкой в задании геометрии диска или тем, файл /boot/boot.b был перемещен без перезапуска /sbin/lilo.
  • LILO — все части LILO успешно загружены.

3.4.7. Диалог LILO с пользователем

Поскольку вторичный загрузчик - это уже достаточно большая программа, она позволяет не просто выполнить какой-то заранее определенный алгоритм действий, но и предоставить пользователю некоторую свободу, дав возможность выбора из нескольких вариантов. Интерфейс взаимодействия пользователя с LILO может быть организован одним из трех способов (или вариантов), а именно:
  • текстовый интерфейс,
  • интерфейс в виде меню,
  • графический интерфейс.

Текстовый интерфейс представляет собой простую командную строку вида

LILO 22.6.1 boot:
После вывода этой строки LILO ждет некоторое время реакции пользователя. У последнего имеется несколько вариантов действий.
  • Нажатие клавиши <TAB> приводит к тому, что на экране отображается список вариантов загрузки (версий ядра или типов операционной системы), примерно такой, как показано на рисунке 1. Первым в этом списке стоит тот вариант загрузки, который выбирается по умолчанию, то есть в том случае, когда пользователь не указывает явно своих предпочтений. После выдачи списка вариантов LILO снова ждет реакции пользователя.
  • Пользователь может (сразу после появления приглашения или после вывода списка вариантов при нажатии <TAB>) ввести название одного из доступных вариантов загрузки. В таком случае LILO загрузит выбранный вариант ядра (или ОС) и запустит его.
  • Если пользователь после появления приглашения просто нажмет клавишу <ENTER>, LILO загрузит вариант ядра, выбираемый по умолчанию.
  • В большинстве систем пользователь может набрать linux single  и LILO загрузит вариант ядра, выбираемый по умолчанию, в однопользовательском режиме.
  • Наконец, вы можете ничего не делать и просто ждать. По истечении отрезка времени, указанного в конфигурационном файле (смотри выше) будет загружен вариант ядра (или системы), выбираемый по умолчанию.
Рис.1. Текстовый интерфейс LILO
Если задать в конфигурационном файле строку
message=/boot/message
то на экран будет выдано сообщение, записанное в файле /boot/message. Пример

Текстовый интерфейс LILO рассчитан на старые "глупые" (dump) терминалы. Но он обладает и некоторыми преимуществами. Сейчас не помню, где именно я нашел следующий совет (с которым я, тем не менее, склонен согласиться): "Если вы хотите избежать любых осложнений в будущем, используйте текстовый интерфейс LILO. Меню-интерфейс смотрится красиво, но он обладает свойством очистки экрана. При этом исчезает из вида выдаваемая BIOS информация, например, список обнаруженных устройств. А иногда эта информация бывает так необходима! Тем более НИКОГДА не используйте графический интерфейс! Он выглядит привлекательно, но если у вас возникнут проблемы с LILO, вы окажетесь в неприятном положении."

Чтобы обеспечить загрузку LILO с текстовым интерфейсом, нужно задать в конфигурационном файле строку

install=text
и переустановить LILO (командой lilo).

Если вы предпочтете интерфейс в виде меню (он появился в LILO начиная с версии 21), то эта строка должна принять вид

install=menu
В настоящее время меню-интерфейс используется в LILO по умолчанию. При этом на экран выдается список вариантов загрузки, каждая строка в котором соответствует одной из подсекций файла /etc/lilo.conf. Ниже списка вариантов выбора загрузки выводится строка ввода, такая же, как и в текстовом режиме, с помощью которой пользователь может задать дополнительные параметы загрузки (см. Рис.2).
Рис.2. Интерфейс LILO в виде меню

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

install=menu
message=/boot/message
menu-scheme=wb:bw:wb:bw
на строки
install=menu
bitmap=/boot/file.bmp
где file.bmp - имя файла с картинкой. Однако, не любой bmp-файл здесь годится. Когда я пытался добиться загрузки в графическом режиме с системе Mandriva Free, у меня ничего не получилось: какой из bmp-файлов, найденных на диске, я ни подставлял, все время команда "lilo -t -v" выдавала сообщение "Неподдерживаемый формат bmp". Так что того, как выглядит экран при выборе графического варианта интерфейса LILO, мне видеть не довелось.

Как происходит загрузка ядра через LILO

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

Файлы загружаемых ядер хранятся в каталоге /boot. Обычно к имени файла ядра добавляется номер версии. Например, если версия ядра 2.4.18, то файл будет иметь имя /boot/vmlinuz.2.4.18. Впрочем, название файла ядра значения не имеет, важно, чтобы он был доступен на этапе загрузки. Вторичный загрузчик читает файл /boot/map, чтобы определить расположение образа загружаемого ядра.

Файл /boot/map содержит "карту" размещения файла ядра и файла с образом виртуального диска initrd, представляющую собой последовательность физических адресов блоков на диске, в которых находятся соответствующие файлы. В процессе обработки map-файла загрузчик последовательно считывает блоки с диска в том порядке, который задан в map-файле и формирует образ соответствующего файла в памяти.

Если заглянуть внутрь map-файла (например, с помощью встроенного просмотрщика из Midmight Commander), мы увидим, что там хранятся какие-то служебные сообщения и названия всех вариантов загрузки. Возможно, там содержится еще какая-то необходимая загрузчику информация, только составить полный список путем простого просмотра файла, очевидно, невозможно.

Вторичный загрузчик LILO все еще использует вызовы функций BIOS для выполнения поставленных перед ним задач, в частности, для считывания с диска блоков, в которых записано ядро. Причина того, что на этом этапе все еще используется BIOS, заключается в том, что если включить во вторичный загрузчик весь код, необходимый для того, чтобы получить доступ к различной аппаратуре, он (вторичный загрузчик) будет очень большим (по крайней мере по сравнению с его сегодняшним размером). Более того, он должен будет уметь распознавать и получать доступ (или предоставлять доступ) к разным типам устройств, таким как IDE и EIDE, а также SCSI и так далее.

Зависимость от BIOS, очевидно, ограничивает возможности LILO. В частности, вторичный загрузчик LILO долгое время не мог получить доступ к секторам жесткого диска, расположенным далее 1023-го цилиндра. Вообще говоря, это было проблемой для всех операционных систем для PC-совместимых компьютеров, поскольку источником проблемы является BIOS. У этой проблемы есть два решения. Первое решение заключается в том, чтобы создавать разбиение диска таким образом, чтобы расположить вторичный загрузчик ниже 1023-го цилиндра. Это является причиной того, что загрузочные файлы помещаются в особом каталоге /boot, который часто размещается в отдельной файловой системе, которая находится в начале жесткого диска.

Второе решение состоит в использовании логической адресации блоков ("Logical Block Addresses" - LBA). В этом случае BIOS "думает", что секторов меньше, чем их есть в действительности.


Вопросы, которые для меня пока остаются неясными:

Где располагается физически вторичный загрузчик? Попов пишет: "LILO поступает просто: первая часть кода при инсталляции получает адрес продолжения в виде списка блоков, в которых и записано это самое "продолжение". "Продолжение" - не обязательно код. Это может быть и список необходимых файлов, но адресуемых физически, как блоки."


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