Процесс загрузки Linux

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

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

Общий обзор процесса[править | править вики-текст]

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

Основные этапы загрузки:

  1. BIOS выполняет загрузочные шаги, специфичные для данного аппаратного обеспечения.
  2. Когда все устройства распознаны и правильно запущены, BIOS загружает и выполняет загрузочный код с одного из разделов заданного загрузочного устройства, который содержит фазу 1 загрузчика Linux. Фаза 1 загружает фазу 2 (значительный по размеру код загрузчика). Некоторые загрузчики могут использовать для этого промежуточный этап (под названием фаза 1,5), поскольку современные диски большого объёма могут некорректно считываться без дальнейшего кода.
  3. Загрузчик зачастую предлагает пользователю меню с доступными вариантами загрузки. Затем он загружает ядро, которое распаковывается в память, настраивает системные функции, такие как работа необходимого оборудования и управление страницами памяти, после чего делает вызов start_kernel().
  4. После этого start_kernel() выполняет основную настройку системы (прерывания, остальные функции управления памятью, инициализацию устройств, драйверов и т. д.), а потом порождает процесс бездействия, диспетчер и отдельно от них — процесс init (выполняющийся в пользовательском пространстве).
  5. Планировщик начинает более эффективно управлять системой, в то время как ядро переходит к бездействию.
  6. Процесс init выполняет необходимые сценарии, которые настраивают все службы и структуры, не относящиеся к уровню ядра, в результате чего будет создано пользовательское окружение, и пользователю будет предоставлен экран входа в систему.

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

Фаза загрузчика[править | править вики-текст]

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

  • Для x86 или x86-64: код с загрузочного сектора раздела диска выполняется в реальном режиме и загружает первую фазу загрузчика (как правило — часть LILO или GRUB).

С этого момента загрузка продолжается. Первая фаза загружает остальной код загрузчика, который обычно спрашивает, какую операционную систему (или вид её сессии) пользователь хочет запустить. Код загрузчика создаётся на основе конфигурационного файла /etc/lilo.conf (для LILO), в котором определены доступные системы. Этот файл содержит, в частности, информацию о загрузочном разделе и расположении ядра для каждой из таких систем, а также дополнительные параметры загрузки, если они заданы. В результате выбора соответствующее ядро загружается в ОЗУ, минимальная начальная файловая система настраивается из файла-образа (initrd), а затем, вместе с соответствующими параметрами управление передаётся новой ОС.

LILO и GRUB имеют определённые различия:[1]

  • LILO не распознаёт файловые системы, поэтому он использует непосредственные (raw) смещения на диске и сведения из BIOS для загрузки данных. Он загружает код меню, а потом, в зависимости от выбора, загружает либо 512-байтные секторы диска для системы, основывающейся на MBR (например, Microsoft Windows), либо образ ядра для Linux.[1]
  • GRUB, наоборот, распознаёт распространённые файловые системы (например, ext2 и ext3).[2] Так как GRUB хранит свои данные в файле конфигурации, а не в загрузочной записи, и имеет интерфейс командной строки, то зачастую параметры GRUB легче поправить или изменить, если они настроены неправильно или повреждены.[3]

GRUB[править | править вики-текст]

  1. Загрузчик 1-й фазы считывается BIOS из MBR (главной загрузочной записи).[4]
  2. Он загружает оставшуюся часть загрузчика (2-ю фазу). Если вторая фаза находится на большом диске, иногда загружается промежуточная фаза 1,5, которая содержит дополнительный код, позволяющий считывать цилиндры с номерами более 1024 (диски LBA). Загрузчик фазы 1,5 хранится (если это необходимо) в MBR или в загрузочном разделе.[4]
  3. Выполняется вторая фаза загрузчика и отображает меню запуска GRUB. Оно также позволяет выбрать среду выполнения и просмотреть параметры системы.
  4. Когда операционная система выбрана, она загружается и ей передаётся управление.[4]

GRUB поддерживает и прямой, и цепной способ загрузки, а также LBA, ext2, и «истинно командно-ориентированную, дооперационную среду на машинах x86». Он имеет три интерфейса: меню выбора, редактор настроек и командную консоль.[4]

LILO[править | править вики-текст]

LILO старше GRUB и практически аналогичен ему в действии, за исключением того, что не содержит интерфейса командной строки. Поэтому все изменения нужно вносить в его настройки и записывать в MBR, после чего систему перезагружают. Таким образом, ошибка в настройках может сделать диск неспособным к загрузке без использования отдельного загрузочного устройства (дискеты и т. п.), содержащего программу для исправления ошибки.[3] Кроме того, LILO не распознаёт файловые системы; вместо этого, адреса файлов-образов хранятся непосредственно в MBR,[3] а BIOS используется для прямого к ним доступа.

Loadlin[править | править вики-текст]

Ещё один способ загрузить Linux — из DOS или Windows 9x, где ядро Linux полностью заменит выполняющуюся копию операционной системы. Это может быть целесообразно, если аппаратное обеспечение должно включаться программно, а соответствующие программы существуют только для DOS, а не для Linux, будучи проприетарным ПО производителя и объектом коммерческой тайны. Этот утомительный метод загрузки уже не очень актуален, так как в Linux есть драйверы для множества аппаратных устройств, хотя в прошлом он был весьма полезен.
Другой пример: когда Linux находится на устройстве хранения данных, которое не предназначено для загрузки из BIOS: DOS или Windows могут загрузить соответствующие драйверы, чтобы обойти такое ограничение BIOS, а затем загрузить оттуда Linux.

Фаза ядра[править | править вики-текст]

Ядро Linux управляет главными функциями, такими как управление памятью, диспетчер задач, ввод-вывод, межпроцессное взаимодействие и общее управление системой. Загрузка проходит в два этапа: на первом ядро (в виде сжатого файла-образа) загружается в память и распаковывается, далее настраиваются такие базовые функции как основное управление памятью. Затем управление в последний раз передается основному процессу запуска ядра. Как только ядро становится полностью работоспособным (т. е. загруженным и выполнившим свой код), оно находит и запускает процесс init, который самостоятельно настраивает пользовательское пространство и процессы, необходимые для функционирования пользовательского окружения и итогового входа в систему. Само ядро переходит в режим бездействия и готовности к вызовам со стороны других процессов.

Этап загрузки ядра[править | править вики-текст]

Ядро при загрузке обычно имеет вид файла-образа, сжатого в формат zImage или bzImage с помощью zlib. В нём содержится головная программа, которая проводит минимальную настройку оборудования, распаковывает образ целиком в верхнюю память и монтирует RAM-диск, если он предусмотрен.[5] После этого она выполняет запуск ядра посредством ./arch/i386/boot/head и процесса startup_32() (для процессоров семейства x86).

Этап запуска ядра[править | править вики-текст]

Источник: Описание процесса загрузки Linux фирмой «IBM»  (англ.) + переведённая версия с того же сайта Подробности процесса загрузки Linux  (рус.)

Функция запуска ядра (также называемая своппер или процесс 0) организует управление памятью (таблицы страниц и страничную организацию памяти), определяет тип процессора и дополнительные возможности (например, наличие математического сопроцессора), а затем переключается к архитектурно-независимому функционалу ядра Linux путём вызова start_kernel().

start_kernel() выполняет множество задач инициализации. Она настраивает обработчики прерываний (IRQ), затем настраивает память, запускает процесс init (первый процесс пользовательского режима), а затем запускает задачу бездействия вызовом cpu_idle(). Следует заметить, что процесс запуска ядра также монтирует инициирующий RAM-диск («initrd»), который ранее был загружен в роли временной корневой файловой системы в фазе загрузки. Это позволяет загружать модули драйверов, не опираясь на другие физические устройства и драйверы, и поддерживать небольшой размер ядра. Корневая файловая система впоследствии подменяется с помощью вызова pivot_root(), который размонтирует временную и заменяет её настоящей корневой ФС, как только последняя станет доступна. Использованная временной системой память затем освобождается.

Таким образом, ядро инициализирует устройства, монтирует указанную загрузчиком файловую систему в режиме «только чтение» и запускает процесс init (/sbin/init), который обозначается как первый процесс, запущенный системой (с идентификатором процесса PID = 1).[1] Соответствующие сообщения выводит ядро (при монтировании файловой системы) и init (при запуске одноименного процесса). Ядро также может выполнить initrd для обработки настроек и инициализации устройств до монтирования корневой файловой системы.[1]

По заявлению компании «Red Hat», детали процесса загрузки на этом этапе можно подытожить так:[2]

« Когда загружается ядро, оно сразу же инициализирует и конфигурирует память компьютера и настраивает различное подключённое к системе оборудование, включая все процессоры, подсистемы ввода-вывода и устройства хранения данных. Затем оно ищет сжатый образ initrd в заранее определённом участке памяти, распаковывает его, монтирует и загружает все необходимые драйверы. Затем оно инициализирует виртуальные устройства, связанные с файловой системой, например LVM или программные RAID-массивы, прежде чем демонтировать образ диска initrd и освободить всю память, ранее занимаемую образом. Потом ядро создает корневое устройство, монтирует корневой раздел только для чтения и освобождает всю неиспользованную память. К этому времени ядро загружено в память и работоспособно. Тем не менее, поскольку нет пользовательских программ для осуществления осмысленного ввода данных в систему, с ней мало что можно делать. »

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

Процесс init (только типа UNIX System V)[править | править вики-текст]

« Init является родителем всех процессов. Его главная задача — создавать процессы по сценарию из файла /etc/inittab. В этом файле обычно содержатся записи, указывающие init породить getty для каждой линии, по которой пользователи могут входить в систему. Он также контролирует автономные процессы, требуемые какой-либо системе. Уровень выполнения — программная конфигурация системы, которая позволяет существовать только заданной группе процессов. Процессы, порождаемые init на каждом из таких уровней выполнения, определяются в файле /etc/inittab.[6] »

По сути init организует и поддерживает всё пользовательское пространство, что включает в себя также проверку и монтирование файловых систем, запуск нужных пользовательских служб и, переключение в пользовательскую среду, когда запуск системы завершится. Он похож на процессы init в Unix и BSD, от которых произошёл, но в некоторых случаях он изменён или переделан. В обычной системе Linux init имеет параметр, известный как уровень выполнения, принимающий значения от 1 до 6 и определяющий, какие подсистемы следует включить. Для каждого уровня выполнения есть собственные сценарии, которые регламентируют различные процессы, участвующие в установлении или снятии данного уровня, и именно эти сценарии считаются необходимыми для процесса загрузки. Сценарии init обычно хранятся в каталогах с именами вида /etc/rc…. Главный файл конфигурации уровней для init — /etc/inittab.[7]

Во время загрузки системы он проверяет, описан ли уровень по умолчанию в /etc/inittab, а если же нет — запрашивает его через системную консоль. Затем он продолжает выполнять все соответствующие сценарии загрузки для этого уровня, включая загрузку модулей, проверку целостности файловой системы (которая монтировалась только для чтения), перемонтирование её для чтения-записи и настройку сети.[1]

В частности, по сообщению Red Hat, процесс init следует такой схеме:[2]

  1. Он просматривает сценарий sysinit, который "устанавливает путь к среде, запускает swap, проверяет файловые системы и делает всё, что необходимо для инициализации системы. Это, в частности, системные и аппаратные часы, специальные процессы для последовательного порта и т. п.
  2. Затем init просматривает конфигурацию, указанную для заданного уровня выполнения.
  3. После этого init устанавливает исходную библиотеку функций для системы. Это определяет, как следует запустить или снять программу и как определить её PID.
  4. Затем он запускает все предусмотренные процессы и создает сессию входа пользователя в систему.

После того, как он породил все заданные процессы, init переходит в режим ожидания и ждет одного из трёх событий:

  1. Нормального или аварийного завершения порождённых процессов.
  2. Сигнала аварии питания.
  3. Запроса от /sbin/telinit на изменение уровня выполнения.[6]

Это относится к программе init в стиле UNIX System V. Другие программы init могут вести себя иначе.

См. также[править | править вики-текст]

Примечания[править | править вики-текст]

Ссылки[править | править вики-текст]