Когда-то давно термин bootstrapping (загрузка) в компьютерной
области означал загрузку бумажной ленты, на которой хранилась программа
начальной загрузки, или же ввод программы начальной загрузки вручную
при помощи расположенных на передней панели переключателей
адреса/данных/управления. Современные компьютеры оборудованы
устройствами, которые значительно упрощают процесс первоначальной
загрузки – однако это не означает, что этот процесс является простым.

Давайте
сначала бросим самый общий взгляд на процесс начальной загрузки Linux,
чтобы охватить картину полностью. Затем мы более подробно рассмотрим,
что происходит на каждом этапе процесса. Ссылки на исходный код,
которые будут приводиться постоянно в процессе изложения, помогут при
изучении дерева исходных кодов ядра и подскажут, где получить
дополнительную информацию.

Ресурса в конце данной статьи.)

Одним
из наибольших достоинств GRUB является то, что он способен понимать
используемые в Linux файловые системы. Вместо того чтобы подобно LILO,
обращаться непосредственно к секторам жесткого диска, загрузчик GRUB
способен загружать ядро Linux с файловых систем ext2 или ext3. Это
достигается благодаря превращению двухступенчатого загрузчика в
трехступенчатый. Ступень 1 (MBR) загружает загрузчик 1.5-ступени,
способный понимать файловую систему, в которой хранится образ ядра
Linux. Примерами могут служитьreiserfs_stage1_5(для загрузки из файловой системы с журналированием Reiser) илиe2fs_stage1_5 (для
загрузки из файловых систем ext2 или ext3). После того, как загрузчик
1.5 ступени загружен и выполняется, может быть загружен загрузчик 2-й
ступени.

После загрузки 2 ступени GRUB способен по запросу показать список имеющихся ядер (которые определяются в /etc/grub.conf, с поддержкой мягких ссылок из/etc/grub/menu.lst и/etc/grub.conf).
Вы можете выбрать нужное ядро и даже передать ему дополнительные
параметры ядра. Также существует возможность воспользоваться оболочкой
с поддержкой командной строки, что обеспечивает большую степень
контроля над процессом загрузки.

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

Ядро

Ручная загрузка в GRUB

Из командной строки в GRUB можно загрузить нужное ядро с указанным образом initrd следующим образом:

grub> kernel /bzImage-2.6.14.2
[Linux-bzImage, setup=0x1400, size=0x29672e]

grub> initrd /initrd-2.6.14.2.img
[Linux-initrd @ 0x5f13000, 0xcc199 bytes]

grub> boot

Uncompressing Linux... Ok, booting the kernel.

Если
известно название ядра, которое вы хотите загрузить, то просто введите
символ прямого слэша (/) и затем нажмите клавишу Tab. После этого GRUB
отобразит список ядер и образов initrd.

После
того как образ ядра оказывается в памяти и ему передается управление от
загрузчика 2-й ступени, наступает стадия ядра. Однако образ ядра не
является исполняемым, это сжатый образ ядра. Обычно это zImage (сжатый
образ размером менее 512KB) или bzImage (большой сжатый образ, размером
более 512KB), который был сжат при помощи zlib. В начале такого образа
ядра располагается программа, которая выполняет минимальную настройку
аппаратного обеспечения и затем распаковывает ядро, хранящееся внутри
образа ядра, и помещает его в верхнюю область памяти. Если имеется
образ начального RAM-диска, то программа также перемещает его в память
и помечает для дальнейшего использования, а затем вызывает само ядро,
после чего начинается загрузка ядра.

При вызове bzImage (образ для i386) выполнение начинается в./arch/i386/boot/head.Sс ассемблерной функцииstart (основные этапы показаны на рисунке 3). Эта программа выполняет основную настройку аппаратного обеспечения и вызывает процедуруstartup_32, располагающуюся в ./arch/i386/boot/compressed/head.S.
Процедура настраивает базовую среду (стек и т.п.) и очищает Block
Started by Symbol (BSS). Затем выполняется декомпрессия ядра при помощи
вызова C-функцииdecompress_kernel(которая хранится в ./arch/i386/boot/compressed/misc.c). После декомпрессии ядра в память происходит его вызов. Это еще одна функция startup_32, но она располагается в файле ./arch/i386/kernel/head.S.

В новой функцииstartup_32
(которая называется swapper или process 0) инициализируются таблицы
страниц (page tables) и обеспечивается подключение функции memory
paging (отображение страниц). Также определяется тип центрального
процессора и сопроцессора для вычислений с плавающей точкой (FPU), если
он имеется, и данная информация сохраняется для последующего
использования. Далее вызывается функцияstart_kernelиз(init/main.c),
которая осуществляет переход в ту часть ядра Linux, которая не зависит
от особенностей конкретной аппаратной платформы. Можно сказать, что это
функция main для ядра Linux.

Рисунок 3. Выполнение основных функций при загрузке ядра Linux для i386
Основные функции в процессе загрузки ядра Linux i386

При обращении к start_kernel
вызывается длинный список функций инициализации, которые выполняют
настройку прерываний, производят дальнейшее конфигурирование памяти и
загружают начальный RAM-диск. После этого вызывается функция kernel_thread (изarch/i386/kernel/process.c), запускающая функциюinit,
которая является первым процессом, выполняющимся в пространстве
пользователя. В заключение запускается idle task, после чего управление
может взять на себя планировщик (scheduler) (после вызова cpu_idle).
Если разрешены прерывания, вытесняющий планировщик (pre-emptive
scheduler) будет периодически перехватывать контроль для поддержки
многозадачности.

В процессе загрузки ядра выполняется загрузка в оперативную память и монтирование начального RAM-диска (initrd), который был загружен в память загрузчиком 2-й ступени. Данныйinitrdслужит
временной корневой файловой системой в оперативной памяти и позволяет
ядру полностью загрузиться, не выполняя монтирование каких-то
физических дисков. Так как модули, необходимые для взаимодействия с
периферийными устройствами, могут являться частьюinitrd,
то ядро получается очень компактным и тем не менее способно
поддерживать самые разнообразные аппаратные конфигурации. После
загрузки ядра корневая файловая система заменяется (при помощиpivot_root); при этом корневая файловая система initrd удаляется и монтируется действительная корневая файловая система.

Вывод функции decompress_kernel

Функцияdecompress_kernel отвечает за те обычные сообщения о разархивировании, которые появляются на экране :

Uncompressing Linux... Ok, booting the kernel.

Функция initrd
позволяет создать компактное ядро Linux, где драйверы скомпилированы
как загружаемые модули. Эти загружаемые модули обеспечивают доступ ядра
к дискам и файловым системам, которые имеются на этих дисках. Также
имеются драйверы для других аппаратных устройств. Так как корневая
файловая система представляет собой файловую систему на диске, то функция initrd
обеспечивает для загрузчика возможность обратиться к диску и
смонтировать действительную корневую файловую систему. Во встраиваемой
системе без жесткого диска initrd может представлять
собой окончательную файловую систему, или же окончательная файловая
система может монтироваться при помощи сетевой файловой системы
(Network File System, NFS).

Init

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

На обычных настольных системах с операционной системой Linux обычно первым запускаемым приложением является/sbin/init. Однако это обязательно. Во встраиваемых системах редко требуется такая обширная инициализация, которую обеспечиваетinit(которая конфигурируется при помощи /etc/inittab). Во многих случаях можно запустить простой shell-скрипт, который запускает необходимые встраиваемые приложения.

Заключение

Как
и сама операционная система Linux, процесс загрузки ядра является
чрезвычайно гибким и универсальным и поддерживает большое количество
процессоров и аппаратных платформ. В самом начале загрузчик loadlin
обеспечивал простой способ загрузки Linux без поддержки каких-либо
необязательных аксессуаров. Загрузчик LILO расширил круг поддерживаемых
функций, однако его недостатком являлось отсутствие поддержки файловых
систем. Последнее поколение загрузчиков, таких как GRUB, позволяет
загружать Linux с самых различных файловых систем (начиная с Minix и
заканчивая Reiser).

Карта сайта: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34