Конспект лекции, прочтённой (в результате оплошности лектора) без слайдов

Досистемная загрузка

Что происходит после включения компьютера? Как туда попадает ОС? Ведь компьютер-=- это железка, выполняющая программы.И сразу так вот хоп — загрузить операционку на него нельзя. Более того, а как вообще в компьютер попадает самая первая программа?

Загрузчик BIOS

BIOS, Basic Input-Output System, подсистема, распознающая устройства и немножко умеющая с ними работать.

Возможности
BIOS не может знать, где на диске лежит ОС, не может даже прочитать произвольное количество данных с диска (тем более, непонятно какое). Зато может принять решение о том, чтобы грузиться вообще из сети. Или с дискетки. Вот когда клавишу “Del” нажимаешь, попадаешь в настройку, и там всё это есть в разделе «Boot».

Задача
Выбрать устройство для загрузки и загрузить оттуда первичный загрузчик стандартного размера

Первичный загрузчик (BootBlock)

Обычно размером один сектор, а то и меньше: на жёстком диске 512 байтов минус таблица разбиения.

Возможности
BootBlock размером менее 500 байтов, но зато на каждом устройстве он свой. То есть знает, как работать с этим и подобными устройствами, в него можно вбить настройки (например, если надо загрузить программу произвольного размера, в каких секторах диска она лежит). Какие-то мелкие настройки этой программе можно передать.

Задача
Выбрать и загрузить вторичный загрузчик. Иногда не выбрать, а просто загрузить, не спрашивая.

Вторичный загрузчик (BootProg)

Теперь мы не зависим (в пределах разумного от размера). Обычно хранится в специальном месте в начале раздела (предусмотрено ФС).

Возможности
Он может работать с ФС, в начале которой лежит, много разных полезных вещей может. Загружать ядро, модули к нему. Настраивать ядро.

Задача
Выбор и загрузка ядра, модулей и старт ОС или загрузка другого загрузчика

Если вторичный загрузчик не умеет загружать ядро этой ОС, он загрузит другой загрузчик, который умеет. Например, Windows и Linux, Linux-загрузчик умеет загружать ядро Linux, но не умеет систем неые файлы Windows, ну и ладно, зато у Windows есть собственный загрузчик, который умеет, и известно, где он лежит. Ну, и загрузим его, пускай разбирается.

В этом месте заканчивается досистемная загрузка. По-хорошему она вообще не зависит от ОС. Сражу скажу — в Linux не используется теоретически правильная трёхступенчатая последовательность загрузи по причине legacy, тяжёлого наследства длинного исторического процесса разработки IBM PC.

Разделы жёсткого диска

Разбиение жёсткого диска на разделы устроено нелогично по причине всё того же legacy.

Полкадра, которого не было в слайдах

Почему бы не взять диск, завести на нём одну ФС и хранить там файлы?


Раздел
Логически «независимая» часть жёсткого диска.

Каждый из разделов можно использовать под разные нужды, поэтому их может быть много.

Отступление о swap. Зачем он? Когда все процессы вместе используют столько памяти, сколько в системе нет. Но ведь они её и не используют одновременно, большая часть памяти заказана, но не используется. Или уже один раз использовалась, а теперь — нет. Но выбросить её нельзя, в ней лежат нужные процессу данные. Поэтому эти неиспользованные куски памяти можно записатьо на диск, а когда в них возникнет нужда (процесс к нм обратится) — прочитать оттуда. Надо отличать swapping, когда процесс выгружается из памяти целиком, чтобы дать место другому процессу, и paging, когда выгружаются только неиспользуемые страницы памяти. Если система начала использовать swapping, надо срочно покупать память. Хранить swap в файле — значит, попусту использовать механизмы файловой системы и увеличивать паразитную нагрузку.

Разбиение диска

  1. MBR (Master Boot Record, место для первичного загрузчика) + в конце её — HDPT (Hard Disk Partition Table). HDPT содержит место для 4-х записей о ФС.
  2. Четырёх разделов маловато. Придумали новый тип раздела: «расширение» таблицы разделов (extended partition). Это — тоже раздел, он занимает всё оставшееся место диска, и у него в начале опять есть HDPT на четыре элемента. Если не хватит этого расширения, внутрь можно вложить ещё одно с ещё четырьмя записями, и т. п. матрёшка такая.
  3. Стандартный способ разбиения диска: 4 записи в главном HDPT — основные разделы (primary). В расширенном разделе допустимо только две записи: одна ссылается на раздел с файловой системой, а если необходимо ещё раздел сделать, то вторая ссылается на вложенный расширенный раздел, и всё повторяется. Вот это уже настоящая матрёшка. Записи в расширенных разделах — дополнительные (в linux-овом fdisk они называются «logical»).
  4. Именование в Linux: основные четыре раздела имеют номера с 1 по 4, независимо от того, это файловые системы, расширение таблицы или пустое место. Номерами с 5 до упора нумеруются только дополнительные разделы, не расширения

Пример

Каждый раздел — это устройство в /dev/, IDE-диски — “hd”, SCSI — “sd”, первый — “a”, второй — “b” и т. д. Если в компьютере один IDE-диск, он называется обычно /dev/hda, а его разделы /dev/hda1, /dev/hfa2 и т. п.

Среди первичных разделов один может быть загрузочный.

Это разбиение характерно для IBM PC.

Досистемная загрузка с помощью LILO

Две системы загрузки — LILO и GRUB. LILO — это LInux LOader. Первичный загрузчик — LI, вторичный — LO. Приметы: есть при загрузке вывелось только L — аппаратные проблемы, Li недозагрузилось, если LI — программные, LO не найден, если LIL — аппаратные или LO побился, если LILO — программные: не найдено или побилось ядро.

Карта размещения

Загрузчики LI и LO — простые, они только умеют загружать некоторые последовательности секторов с диска. Каких секторов? Это определяется картой размещения.

LI (обычно записывается в MBR) умеет грузить просто несколько секторов с определённого места (обычно — в начале соотв раздела). Сколько и откуда? А прямо внутри LI это и впишем. Так что получается, что если мы меняем вторичный загрузчик, надо переписать и первичный, вдруг место или размер вторичного изменились.

LO должен загрузить ядро и стартовый виртуальный диск (a.k.a. initrd), передать ядру параметры. Или загрузить вторичный загрузчик. Где лежат ядро и initrd? А где-то в файловой системе, причём необязательно в секторах подряд. Значит, надо составить карту: список секторов, в которых они лежат. Вот эту карту и надо присобачить к LO, и делать это всякий раз, когда то, что надо грузить LILO, как-то меняется.

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

Карта размещения, ядро и стартовый виртуальный диск лежать в /boot.

Если несколько пунктов меню (несколько ядер, загрузка других ОС) — это всё надо подготовить заранее.

Cтартовый виртуальный диск

LILO (точнее, LO) — не настоящий вторичный загрузчик, скорее, полуторный: он не может подгружать модули ядра и не разбирается в файловых системах. Только сектора грузит в память. Например, для того, чтобы смонтировать файловую систему с жёсткого диска, необходим драйвер жёсткого диска, то есть модуль ядра. Но взять его с этого диска нельзя, потому что он и нужен для доступа к диску. И кто будет компоновать модуль с ядром? LO этого не умеет.

Можно собрать такое ядро, в котором есть все базовые драйверы, как в 90-х. Всякий раз надо пересобирать ядро? Это тяжело, не имея опыта.

Если LO умеет загрузить один файл в память, то несложно загрузить два. Первый — это ядро, а второй — это образ файловой системы в памяти (стартовый виртуальный диск), ядро его смонтирует, а там — модули, пара-тройка утилит (mount и sh, например), какие-то мелкие настройки и командный сценарий, который, все нужные действия делает.

Такой вот настоящий, большой вторичный загрузчик, возможности которого не ограничены, потом у что он Linux.

Системная загрузка

В конце концов initrd смонтирует корневую файловую систему, размонтирует себя (чтобы память не занимать) и запустит оттуда настоящий init — папу всех процессов. Linux начинает работать.

Определение устройств

Далеко не все модули лежат в initrd, например, звуковая карта, видео, всякие не нужные для загрузки автоматически определяемые устройства. Хотя можно всё напихать и в initrd, есть даже такой дистрибутив на базе Sisyphus: RAD Linux, он предназначен для маршрутизаторов и всяких сетевых устройств, загружается по сети или как-то ещё, и представляет собою один сплошной initrd, загружаемый в память, и работающий как есть.

Распознаванием устройства занимается служба udev. Например, если ядро распознало устройство с некоторым идентификатором, но не знает, что это такое, оно посылает udevd сообщение «вот, появилось какое-то устройство». Демон udevd говорит «о, так это ж BlueTooth», и смотрит в специальную таблицу, где написано «модуль ядра подгрузить такой-то, создать такую-то файл-дырку в /dev с такими-то правами» и ещё что-то, например, запуск каких-то программ. И то же самое при удалении устройства.

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

Запуска служб

Папа всех процессов управляется файлом /etc/inittab — один из самых старых файлов в UNIX, поэтому его синтаксис хитрый. Файл небольшой, потому что он запускает командный сценарий rc, а уже rc запускает все службы.

Когда-то всё, что надо запускать в системе складывалось в один сценарий /etc/rc. Но это неудобно, все службы в одном сценарии, поэтому при удалении и обновлении служб приходится редактировать этот очень длинный файл.

Схема “.d

Это способ перейти от монолитного файла “имя->имя.d/часть1”, “имя.d/часть2”,...

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

Или правила для udevd, если поддержка BlueTooth вообще установлена, появляются соотв. правила в /etc/udev/rules.d/80-bluetooth.rules, которые она носит с собой. Нет поддержки BlueTooth в системе — нет файла.

Получается, что “имя.d/” — это настроечный файл (или сценарий на sehll), распределённый по файлам каталога по принципу «одна сущность — один файл».

Start/Stop сценарий

Схема “.d” для старта и останова служб имеет дополнительный плюс — самостоятельный запуск файлов. Если сценарий старта был монолитный, то отдельную службу остановить или перезапустить модно было бы только руками. А если попилить по принципу «одна служба — один сценарий», можно сделать такой сценарий старт-стопным. То есть оформить как программу на shell, принимающую стандартные параметры start и stop, что означает «запустить службу» и «остановить службу» (при этом параметры самих демонов могут быть какими угодно).

Так что при старте системы запускается последовательность файлов из /etc/init.d с параметром start, а при останове — stop.

Уровни выполнения

Есть несколько т. н. уровней выполнения, то есть профилей запуска системы, изменение состояния системы трактуется как переход с уровня на уровень. Переход на уровень 0 — это выключение системы, на уровень 6 — перезагрузка, а остальные — это профили запуска. 1 — однопользовательский вариант, запускается только shell, 2 — многопользовательский без сети (shell плюс несетевые службы), 3 — многопользовательский с сетью (то же плюс сетевые службы) и 5 — то же плюс графическая оболочка (4 и 7 можно использовать по своему усмотрению).

Фактически, переход с уровня на уровень просто меняет список служб, которые запущены и остановлены, и просто надо некоторые старт-стопные сценарии запустить с параметром start, а некоторые — с параметром stop.

Какие и в каком порядке сценарии запускаются при переходе на уровень, скажем, 5? Все эти сценарии лежат в каталоге /etc/rc/rc5.d/, и называются так: сначала “D” или “K”, потом — двузначный номер, потом имя; причём все они — символьный ссылки на настоящие сценарии в init.d. Старая добрая “.d” схема.

На букву “K” (Kill) начинаются файлы, которые надо запустить с параметром stop, а на букву “S” (Start) — которые надо запустить с параметром start. А цифры нужны для упорядочивания, т. к. сценарии запускаются в лексикографическом порядке, сначала с меньшими числами, затем — с большими.

Итого, при старте системы выполняются старт-стопные сценарии с параметром start просто подряд.

Getty

В конце концов init запускает утилиту mingetty для всех консолей. Mingetty проверяет, есть ли человек за клавиатурой или нет. Если человек есть (то есть он начал нажимать какие-то кнопки), то mingetty запускает login, пользователь вводит идентификационную информацию, пароль — система готова к работе.

Трудности, неприятности и особенности

Многосистемный компьютер:

  1. Не менее одного раздела на систему (нельзя удалить файлы и образовать место для установки Linux)
  2. Надо настроить загрузчик так, чтобы он загружал все нужные ОС (для виндовз в /etc/lilo.conf надо просто указывать other=/dev/раздел_с_windows).
  3. С дополнительных разделов виндовз не грузится.
  4. От переразметки диска меняется именование разделов, виндовз при этом может перестать работать. Виндовз2000 и выше умеет переименовывать разделы «обратно», но для этого ему надо сперва загрузиться.
  5. При установке виндовз затирается LI в MBR, необходимо загрузиться с LiveCD, смонтировать корневой каталог с /etc/lilo.conf и заново запустить lilo. (Наверное, стоит нарисовать такой сценарий, который это сам делает в LiveCD).
  6. Существует несколько вариантов представления одной и той же геометрии диска (попытка впихнуть большое число секторов и дорожек в старый формат, куда эти числа не помещаются). Если старый загрузчик использовал один формат, а новый использует другой, старый может не заработать. То есть Linux грузится, а виндовз — нет, хотя диск монтируется и все файлы в порядке. Тогда начинается самое неприятное место, потому что тут много знания применять надо и действовать вручную.

Запись на NTFS: ntfs3g и captive