Заочная Школа Программистов
Студия "Unix изнутри"
iunix.narod.ru
Итак, ядро 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.
В ходе выполнения эта функция делает следующее: