|
Приложение BB.1. Обзор исходного текста ядра LinuxВ этой главе мы пытаемся по порядку об'яснить исходный текст ядра Linux, пытаясь помочь читателям понять, как структурирован исходный текст, и как описаны соответственные части Linux.Мы преследуем цель близко познакомить начинающего программиста на языке Си с общим устройством Linux. В качестве отправной точки обзора возьмем загрузку системы. Для осознания этого материала требуются хорошее знание языка Си и практически полное представление о концепциях UN*X и архитектуре ПК. В этой главе, однако, вы не встретите текстов на Си, а увидите лишь ссылки на истинный текст. Подробная информация о ядре находится в предыдущих главах, здесь же мы можем увидеть лишь обзорный материал. Любой путь, встречающийся в этой главе, относится к основному кодовому дереву каталогов, обычно это /usr/src/linux. Большинство информации, представленной в главе, взята из Linux 1.0, однако здесь встречаются ссылки на более поздние версии. Любой параграф в этой главе, выделенный так же, как этот, означает описание изменений в ядре по отношению к Linux 1.0. Если в параграфе нет подобных ссылок, это означает, что исходный текст не претерпел изменения в версиях 1.0.9 - 1.1.76. Иногда выделенные места появляются в тексте в качестве ссылок на исходный текст. B.2. Загрузка системыВо время загрузки ПК процессор 80x86 запускается в режиме реального времени и запускает код ROM-BIOS по адресу 0xFFFF0. PS BIOS проводит тестирование системы и инициализирует вектор прерывания на 0-й физический адрес. После этого она загружает сектор загрузочного устройства по адресу 0x7C00 и обращается по этому адресу. Это устройство обычно представляет собой жесткий диск или накопитель в дисководе. Данная выкладка сильно упрощена, однако она дает представление о инициализации ядра. Основная (первая) часть ядра Linux была написана на ассемблере 8086 (boot/bootsect.s). Во время запуска она помещает себя по абсолютному адресу 0x90000, считывая следующие 2Кб кода с загрузочного устройства по адресу 0x90200 и часть ядра по адресу 0x10000. Во время загрузки системы появляется сообщение "Loading...". Далее контроль передается коду в boot/Setup.S (другой исходник режима реального времени на ассемблере). Установленная часть определяет остальные компоненты системы и тип карты vga. Если нужно, она может дать право выбора видеорежима. Затем она переносит всю систему с адреса 0x10000 по адресу 0x1000, включает защищенный режим и обращается к остальной части системы (по адресу 0x1000). Следующим шагом является распаковка ядра. Код по адресу 0x1000 берется из zBoot/head.S, которая устанавливает регистры и вызывает decompress_kernel(), которая создает zBoot/inflate.c, zBoot/unzip.c и zBoot/misc.c. Распакованная информация помещается по адресу 0x1000000 (1Мб), поэтому Linux не может быть запущена на компьютере с ОЗУ, меньшим 1Мб. Сокрытие ядра в файле gzip делается Makefile и утилитами в каталоге zBoot. Среди них есть занимательные программы. Ядро версии 1.1.75 помещает каталоги boot и zBoot в arch/i386/boot. Это изменение позволяет ядру подстраиваться под разные архитектуры. Распакованный код запускается по адресу 0x1010000, где делаются все 32- битные установки: загружаются IDT, GDF и LTD, производятся установки процессору и сопроцессору, устанавливаются страницы и вызывается подпрограмма start_kernel. Исходные тексты предыдущих операций находятся в boot/head.S. Это наиболее изощренный код во всем ядре. Помните, что в случае возникновения ошибки во время выполнения предыдущих шагов компьютер остановит работу. ОС не может справляться с ошибками, если она не полностью установлена. start_kernel помещается в init/main и никогда не прекращает работу. Единственное, что до этого момента написано на Си - это управление прерываниями и системный вызов enter/leave (однако и здесь большинство макросов нвписано на ассемблере). В.2 После обработки самых тонких вопросов, start_kernel инициализирует все по отдельности части ядра.
После этого ядро готово к move_to_user_mode() (перемещение в пользовательский режим. Затем 0-й процесс, так называемая идеальная задача, продолжает функционировать в бесконечном цикле. Процесс init петаетса запустить /exec/init, или /bin/init, или /sbin/init. Если ни один из перечисленных методов не запускается, система запускает "/bin/sh /etc/rc" и ведает основную оболочку на первый терминал. Эта процедура была написана в Linux 0.01, когда ОС состояла из одного ядра и не поддерживала операцию login. После запуска функцией exec() программы init с одной из стандартных позиций (предположим что мы находимся в одной из них), ядро не контролирует процесс работы программы. Его ролью в этот момент становится поддерживать процессы с помощью системных вызовов и обслуживать асинхронные события, такие как прерывания аппаратного обеспечения. Многозадачность также устанавливается до этого, поэтому управлением доступа задач с помощью fork() и login занимается программа init. Данный обзор рассмотрит обслуживание ядром асинхронные события, также подробно как размещение информации и организацию кода. |
helloworld.ru © 2001-2021 Все права защищены |
|
|