Заочная Школа Программистов
Студия "Unix изнутри"
iunix.narod.ru

От автора.
К сожалению, работа над выпусками идет гораздо медленнее, чем предполагалось. Поэтому, было принято решение разбивать выпуски на более мелкие части.
В этом выпуске описывается процессы, которые проиходят сразу после загрузки ядра Linux в память.
С удовольствием выслушаю ваши предложения и замечания. Пишите мне на адрес iunix@narod.ru.

Процесс первоначальной загрузки.

Часть 2. Подготовка ядра Linux к работе

Итак, ядро Linux загружено в память. Что же просходит дальше?
В прошлом выпуске говорилось, что загрузчик последней стадии загружает ядро в память и передает ему управление. Это правда, но не вся.
Дело в том, что ядро Linux состоит из двух частей - собственно образа ядра и процедуры setup. Эти две части загружаются по разным адресам: Процедура setup - по адресу 0x00090200. Оставшаяся часть ядра - производится либо по адресу 0x00010000 (так называемая загрузка "в нижние адреса" для ядер малого размера, собираемых командой "make zImage"), либо по адресу 0x00100000 (называется загрузкой "в верхние адреса" для больших ядер, собираемых командой "make bzImage"). Это, кстати, означает, что такое ядро не может быть запущено на компьютере с объемом памяти, меньшим 1 Мб.
Необходимо сделать еще одно дополнение к предыдущему выпуску. Может возникнуть вопрос, как же осуществляется загрузка ядра в реальном режиме процессора в память выше 1 мегабайта? Эту проблему решает загрузчик LILO. Он загружает с диска часть ядра, размером 64 Кбайта и вызывает функцию BIOS, которая переносит загруженный фрагмент в верхнюю память (с временным переключением в защищенный режим и прочими приседаниями). После чего процесс повторяется до тех пор, пока не будет загружено все ядро.

1. Настройка аппаратного окружения для работы ядра
Итак, после загрузки ядра в память управление передается функции setup(). Процессор еще работает в реальном режиме. Текущая задача состоит в том, чтобы обнаружить и в нужном порядке инициализировать все имеющиеся в компьютере аппаратные устройства. И хотя BIOS уже проинициализировал большую часть аппаратуры, ядро Linux инициализирует все устройства по-своему. В частности, определяется объем имеющейся оперативной памяти, тип видеоадаптера, переинициализируются дисковые накопители. Отчасти это связано с тем, что Linux работает в защищенном режиме, в то время как BIOS - в реальном, и переключение между этими режимами - довольно медленная процедура.
Можно сказать, что функция setup() создает среду для работы ядра и как бы избавляет его от тяжелого наследия реального режима, в котором нет поддержки многозадачности, размер памяти ограничен 1 мегабайтом, а разрядность процессора - 16 битами. Ядро начинает работать уже в "дружественной" обстановке.

2. Настройка программного окружения для работы ядра.
Как и любая программа, ядро Linux требует для свой работы правильно настроенный стек, инизиализированные значения глобальных переменных и много чего еще. И если для обычной программы все эти действия будут выполнены стандартной библиотекой, функции которой будут выполнены еще до вызова функции main() (про это можно прочитать в статье "Как запускается функция main() в Linux" [1]), то ядро Linux само должно позаботиться о решении этой проблемы.
Кроме того, файл с ядром Linux чаще всего упакован, чтобы сохранить место на диске, и уменьшить время его копирования в память (что становится актуальным при загрузки с дискеты или по сети).
Эти проблемы решает функция startup_32,находящаяся в файле /usr/src/linux-2.4.2/arch/i386/boot/compressed/head.S.
В ходе выполнения эта функция делает следующее:

Итак, после выполнения этой функции ядро готово к работе. После этого вызывается другая функция startup_32(), уже из распакованного ядра.
Тут может возникнуть небольшая путаница. Как могут быть в одной программе две функции с одинаковыми именами? На самом деле эта проблема решается очень просто. Одна функция startup_32() находится внутри запакованного ядра, а вторая - в его распаковщике. Во-вторых, процессор вызывается функции не по имени, а по адресу. А уж адреса-то у них разные.

Продолжение следует

Литература
0. http://iunix.narod.ru/material/_N1_bootstrap.html Предыдущий выпуск рассылки.
1. Hyouck "Hawk" Kim "Как запускается функция main() в Linux", Перевод Андрея Киселева.
2.
http://www.linuxgazette.com/issue70/ghosh.html "Bootstrapping a Linux system - an Analysis"
3. http://gazette.linux.ru.net/lg70/articles/rus-ghosh2.html "Bootstrapping, или как Linux сам себя ставит на ноги. Анализ процесса начальной самозагрузки"
4. Ядро ОС Linux. Руководство системного программиста.
5. http://www.moses.uklinux.net/patches/lki.sgml Tigran Aivazian "Linux Kernel 2.4 Internals"
Hosted by uCoz