report4.docx
Санкт-Петербургский политехнический университет Петра Великого Институт Информационных Технологий и УправленияКафедра компьютерных систем и программных технологий
Отчёт по практической работе № 4по предмету «Проектирование ОС и компонентов»
Процесс загрузки операционной системы Linux
Работу выполнил студент гр. 63501/3 Мартынов С. А. Работу принял преподаватель Душутина Е. В.Санкт-Петербург 2016
Содержание
Большинство компьютерных систем могут исполнять только команды, находящиеся в оперативной памяти компьютера, в то время как современные операционные системы в большинстве случаев хранятся на жёстких дисках, загрузочных CD-ROM, USB дисках или в локальной сети.После включения компьютера в его оперативной памяти нет операционной системы. Само по себе, без операционной системы, аппаратное обеспечение компьютера не может выполнять сложные действия, такие как, например, загрузку программы в память. Таким образом мы сталкиваемся с парадоксом: для того, чтобы загрузить операционную систему в память, мы уже должны иметь операционную систему в памяти.Решением данного парадокса является использование специальной компьютерной про- граммы, называемой начальным загрузчиком. Эта программа не обладает всей функцио- нальностью операционной системы, но её достаточно для того, чтобы загрузить другую программу, которая будет загружать операционную систему. Часто используется много- уровневая загрузка, в которой несколько небольших программ вызывают друг друга до тех пор, пока одна из них не загрузит операционную систему.Рассмотрим стандартный процесс загрузки Linux системы с момента подачи питания до получения доступа к командному интерпретатору.
BIOS
При включении питания компьютера, в его оперативной памяти отсутствуют какие-либо данные, поэтому управление компьютером может осуществляться только аппаратным обеспечением. На Intel-овских платформах начальная загрузка операционной системы осуществляется посредством так называемой "базовой системы ввода/вывода"или BIOS.После включения компьютера блок питания проверяет все необходимые уровни напря- жений. Если все уровни напряжений соответствуют номинальным, то на материнскую плату поступит сигнал PowerGood. До появления этого сигнала на вход процессора пода- ется сигнал RESET, который удерживает процессор в сброшенном состоянии. Но после получения сигнала PowerGood от блока питания сигнал RESET будет снят и процессор начнет выполнять свои первые инструкции. При этом процессор стартует от вполне из- вестного состояния: командный регистр CS содержит 0xFFFF, указатель команд (регистр IP) содержит 0, сегментные регистры данных и стека содержат 0. Таким образом, после снятия RESET процессор в реальном режиме выполняет инструкции, размещающиеся в области ROM BIOS, начинающейся с адреса FFFF:0000 (физический адрес, соответственно,- 0xFFFF0). Размер этой области, очевидно, составляет 16 байт, вплоть до конца макси- мально адресуемого адресного пространства в реальном режиме - 0xFFFFF. По этому адресу располагается инструкция перехода на реально исполняемый код BIOS.По соображениям снижения стоимости код BIOS в относительно современных материнских платах хранится в постоянной памяти (ПЗУ) в сжатом виде. Только небольшая его часть, используемая на самых первых этапах загрузки, является непосредственно исполняемой. Поэтому первая задача, которая решается сразу после включения питания, заключается в том, чтобы инициализировать контроллер DRAM, декомпрессировать основной код BIOS и загрузить его в ту область оперативной памяти (RAM), которую именуют "теневой"(shadow RAM).Эта область затем защищается от записи и управление передается на записанный в нее исполняемый код BIOS. Теневая память в ходе дальнейшей работы отдана в полное владение чипсета материнской платы; операционная система к ней доступа не имеет. Но аппаратными средствами обеспечивается отображение теневой памяти на те области, которые в реальном режиме работы доступны для старых операционных систем типа MS-DOS, так что последние обнаруживают код BIOS именно там, где ожидают его найти.Исполняемый код BIOS вначале реализует функцию начального самотестирования (POST- Power-On Self Test). При этом тестируются процессор, память и системные средства ввода/вывода, а также производится конфигурирование программно-управляемых ап- паратных средств компьютера. Кроме того производится поиск и обнаружение перифе-
рийных устройств. При этом производится сравнение установок, записанных в CMOS (Complementary Metal Oxide Semiconductor) с тем, что реально обнаружено в системе. Некоторые несовпадения, например, различие типов флоппи-дисковода, могут быть допу- стимы и процесс загрузки продолжится. Другие ошибки, например, отсутствие видеокарты, приводят к невозможности дальнейшей загрузки. Но все сообщения о выявленных на этом этапе ошибках сводятся только к тому, что раздастся несколько коротких звуковых сигналов (каждый вендор имеет свой код звуковых ошибок, который нужно смотреть по документации на материнскую плату).Некоторые типы периферийных устройств могут содержать расширения BIOS в собствен- ных ПЗУ. В таком случае устанавливаются соответствующие ссылки на эти расширения. Основная причина, по которой это необходимо, заключается в том, что по историческим причинам размер первичного загрузчика (загрузчика первого этапа) на персональных компьютерах ограничен величиной 446 байт. Этого явно недостаточно для того, чтобы включить в этот загрузчик драйверы всех периферийных устройств (например, дисплея и устройств хранения данных), которые могут понадобиться на этапе начальной загрузки системы. Тем более, что драйверы могут различаться для однотипных устройств от разных производителей. Поэтому функция загрузки некоторых драйверов возлагается на BIOS.После завершения процедуры самотестирования та часть кода BIOS, которая реализует процедуры самотестирования (POST), удаляется из оперативной памяти. Оставшаяся часть BIOS, реализующая функции BIOS (runtime services), остается в ОП. Она будет доступна в последующем для загруженной операционной системы.Первой задачей той части BIOS, которая осталась в ОП, является поиск активного загру- зочного устройства. Список устройств, которые могут являться загрузочными, хранится в энергонезависимой памяти компьютера (CMOS), а порядок просмотра этого списка явля- ется одним из настраиваемых параметров BIOS. Загрузочным устройством может быть дискета, CD-ROM, раздел жесткого диска, сетевое устройство или даже USB-устройство (флеш-диск). Поиск загрузочного устройства осуществляется путем вызова прерывания INT19h BIOS.Процедура обработки прерывания INT19h состоит в том, что считывается сектор с коорди- натами Cylinder:0 Head:0 Sector:1 на очередном устройстве, его содержимое помещается в ОП по адресу 0000:7С00h, после чего осуществляется проверка, является ли этот сектор загрузочным, то есть содержит ли он код первичного загрузчика. Загрузочные сектора помечаются "волшебным"числом 0x55AA в позиции 0x1FE = 510. Это последние два байта сектора. Наличие (или отсутствие) такого кода в последних байтах сектора позволяет программе BIOS решить, является ли данное устройство загрузочным.
Как только программа обработки прерывания обнаружит, что загруженный в память сектор содержит это самое "магическое число"0x55AA, управление передается на начало этого сектора (по абсолютному адресу 0000:7С00h). Дальнейшие события зависят от того, где обнаружен загрузочный сектор - на жестком диске или на одном из других устройств: дискете, CD или flash-диске (на всех этих устройствах обычно создается образ загрузочной дискеты).Если при проверке загрузочный сектор не обнаружен ни на одном устройстве, вызывается прерывание INT18h. Когда-то (в первых персональных компьютерах, производимых ком- панией IBM) это прерывание служило для вызова интерпретатора ROM-BASIC, который дальше управлял работой компьютера. Клоны IBM-PC не имеют BASIC в ROM-памяти и теперь это прерывание используют для организации загрузки по сети. Но мы не будем рассматривать эту ветку развития событий и вернемся к тому случаю, когда прерыва- ние INT19h обнаружило загрузочный диск и передало управление находящейся в нем программе.Примечание: Как следует из приведенного выше описания, BIOS выполняет массу работы по тестированию системы. Ядро Linux потом повторно проделывает всю эту работу. Как правило, после загрузки ядра большинство функций BIOS не используется (хотя есть некоторые исключения) и, тем не менее, этот уже бесполезный код BIOS сохраняется в "теневой"памяти компьютера.
Смещение | Размер | Содержание |
0x000 | 446 байт | Главная загрузочная запись (Master Boot Record) |
0x1BE | 64 байта | Таблица разбиения диска |
0x1FE | 2 байта | "Магическое число"(0x55AA) |
Таблица 1: Структура главного загрузочного сектора.
Master Boot Record и Boot Record
После того, как BIOS нашел загрузочное устройство, он передаёт управление программе, которая находилась в самом первом секторе этого диска или дискеты (физический адрес: цилиндр 0, головка 0, сектор 1). Теперь эта программа загружена в память и именно она управляет ходом дальнейшей загрузки. Со времен MS-DOS эту программу принято называть загрузочной записью (Boot Record), а первый сектор любого диска или дискеты - загрузочным сектором (Boot Sector).Размер сектора на устройствах хранения данных равен 512 байтам. Существует три варианта загрузки ядра Linux[Т.Айвазяна]:с помощью загрузочного сектора Linux, загружающего непосредственно ядро (этот загрузочный сектор);с помощью специального загрузчика типа LILO или GRUB;с помощью программ, загружающих Linux из другой ОС. Рассматривать только второй вариант, как наиболее распространенный.С появлением жестких дисков большого объема, которые стали разбивать на разделы, небольшой загрузчик, размещаемый в загрузочном секторе и загружающий непосредствен- но ядро, перестал справляться с возросшим объемом задач. Надо было не просто загрузить файл с определенного физического адреса, но и найти загрузочный раздел перед этим. К тому же часть места, отведенного для загрузочной записи, отняла таблица разделов жесткого диска. Поэтому старая загрузочная запись была перенесена в первый сектор так называемого "активного"раздела, а в самый первый сектор на жестком диске стали записывать другую программу, задачей которой было найти "активный"раздел и загрузить программу из этого раздела. Первый сектор жесткого диска стали называть главным загрузочным сектором (а соответствующую программу - главной загрузочной записью или Master Boot Record, MBR). На жёстком диске MBR находится по тому же физическому адресу, что и BOOT-сектор на дискете (цилиндр 0, сторона 0, сектор 1). Его структура представлена в табл. 1
Это "Магическое число"0x55AA, является признаком того, что диск является загрузочным. Содержащаяся в MBR такого диска таблица разбиения определяет 4 первичных раздела жесткого диска. Первые 446 байт MBR содержат небольшую программу, а также текст сообщений об ошибках, которые могут возникнуть в ходе ее выполнения.Основная задача главной загрузочной записи состоит в том, чтобы найти и загрузить в оперативную память собственно загрузчик операционной системы. MBR сканирует таблицу разделов (partition table) в поисках первого (обычно он и единственный) активного раздела (раздела, помеченного как "загрузочный"). Если в таблице разделов активный раздел не обнаружен или хотя бы один раздел содержит неправильную метку, а также если несколько разделов помечены как активные, выдаётся соответствующее сообщение об ошибке. Когда активный раздел найден, программа считывает в оперативную память первый сектор активного раздела.Практически все загрузчики современных операционных систем состоят из двух частей: загрузчика первого этапа (или первичного загрузчика), который имеет достаточно малый размер, чтобы разместиться в загрузочном секторе, и значительно большего по объему загрузчика 2-го этапа (или вторичного загрузчика), который может храниться уже где угодно на загрузочном носителе, обычно в разделе, содержащем корневую файловую систему. Загрузчик первого этапа может быть размещен как в главном загрузочном секторе диска, так и в загрузочном секторе активного раздела. Если вам приходилось устанавливать Linux, вы знаете, что программа инсталляции предоставляет пользователю такой выбор. Будем пока для определенности считать, что загрузчик 1-го этапа мы поместили в первый сектор активного раздела.Итак, главная загрузочная запись отыскала активный раздел и загрузила из него в память загрузчик первого этапа, который теперь отвечает за продолжение процесса загрузки. Загрузчик первого этапа имеет такой же небольшой размер, как и код загрузочной записи диска, то есть не более 446 байт. Поэтому и сделать он может не больше, а именно - только загрузить основной загрузчик. Еще более затрудняет ситуацию то, код загрузчика первого этапа пока не имеет доступа к файловой системе и, следовательно, определяет расположение программ на диске, используя только информацию о физических секторах и низкоуровневые вызовы BIOS. Поэтому эта программа имеет единственной целью – загрузку и запуск на выполнение загрузчика второго этапа.
Загрузчик 2 этапа операционной системы
Итак, отработали маленькие программы, которые расположены в главной загрузочной за- писи диска (MBR) и в первом секторе активного раздела (Boot Record), то есть первичный загрузчик ОС. Код первичного загрузчика уже различен в разных операционных систе- мах и является, частью загрузчика этой ОС (или какого-то универсального загрузчика, типа GRUB). Два основных загрузчика – это LILO и GRUB. LILO (LInux LOader) – это "родной"загрузчик операционной системы Linux, который, вытесняется универсальным загрузчиком GRUB (GRand Unified Bootloader).Главная задача, которая стоит перед загрузчиком любой операционной системы, заклю- чается в том, чтобы перенести в память ядро операционной системы и передать этому ядру управление дальнейшим функционированием компьютера. При этом современные загрузчики позволяют выбрать ядро из нескольких возможных вариантов как одной и той же операционной системы, так и загрузить ядра разных ОС. Некоторые загрузчики (в частности, GRUB) предоставляют пользователю возможность выполнения некоторых команд, то есть они представляют собой уже некоторое подобие командного процессора.Одна из основных задач ядра – управление железом, которое составляет аппаратную часть компьютера. Поэтому ядро после запуска производит опрос железа. Если драйвер найден- ного устройства вкомпилирован в ядро, устройство инициализируется. Однако стандартное ядро дистрибутива не может содержать драйверы для всех устройств, имеющихся в ком- пьютере. Драйверы устройств, отсутствующие в ядре, надо загрузить из соответствующих файлов. После загрузки ядро должно запустить процесс init, который. Код программы init лежит где-то на носителе, доступ к которому тоже предоставляет файловая система.Но файловая система не является частью ядра, драйвер файловой системы надо загрузить с того же диска. Корневая файловая система на загрузочном устройстве может быть самого разного типа (fat, ext2, reiserfs и так далее), может быть сжата, зашифрована. Получается замкнутый круг: чтобы подключить загрузочное устройство, надо получить доступ к файловой систем, а для этого надо подключить загрузочное устройство.Решение этой проблемы было найдено за счет временного подключения виртуальной файловой системы, образ которой хранится в файле рядом с образом ядра. При этом ми- нимальное число самых необходимых драйверов включается в само ядро, а все остальные размещаются на виртуальном диске, в виде подгружаемых модулей. Когда осуществля- ется загрузка (в частности, на неизвестном оборудовании) ядро опрашивает аппаратуру и загружает только те модули, которые соответствуют обнаруженной конфигурации. В частности, и LILO и GRUB создают в оперативной памяти виртуальный диск и развора- чивают на нем временную корневую файловую систему, содержащую необходимые ядру
драйверы устройств и служебные файлы. Сжатый образ этой файловой системы обычно располагается в одном каталоге с образом ядра в виде файла, содержащего дополнительные компоненты, например, драйверы некоторых устройств.
Загрузка и инициализация ядра
Во время загрузки Linux на консоль выводится большое количество сообщений, в том числе и сообщений о действиях, выполняемых ядром при его инициализации. Эти сообщения обычно быстро проскакивают, и их невозможно прочитать. Ещё эти сообщения могут быть скрыты за заставкой. Но все эти сообщения сохраняются и их можно увидеть после завер- шения загрузки, воспользовавшись командой dmesg. Протоколирование этих сообщений осуществляется демоном протоколирования klogd (он запускается как один из потоков ядра). Klogd сохраняет эти сообщения в специальном буфере ядра, содержимое которого выдается по команде dmesg. Кроме того, klogd передает эти сообщения демону системного протоколирования syslogd, который записывает их в файл /var/log/messages. Благодаря этому они и доступны для просмотра и анализа после завершения запуска системы.Ядро хранится на диске в сжатом виде. Только его первая часть не сжата. Когда за- грузчик перенесет ядро в память, эта несжатая часть ядра выполняет декомпрессию оставшейся части. Несжатая часть кода, которая содержится в начале ядра, написана на ассемблере, ее можно найти в файлах arch/i386/boot/setup.S, arch/i386/boot/video.S и arch/i386/kernel/head.S.Код, хранящийся в файлах arch/i386/boot/setup.S и arch/i386/boot/video.S, отвечает за получение системной информации от BIOS и размещение ее в подходящих местах системной памяти. Кратко перечислим основные действия, которые выполняет эта часть ядра:Проверка того, что ядро загружено правильно. Осуществляется проверкой сигнатуры в конце кода запуска. Если она не найдена, то копируются секторы с запускающим кодом и сигнатура ищется снова. Если опять безуспешно, то выдается сообщение "No setup signature found ...".Проверка на возможность работы с верхней памятью. Если образ ядра слишком большой (и поэтому загружен в верхнюю память), а код несжатой части ядра не может работать с образами, расположенными в верхней памяти, то загрузка прекращается и выдачей сообщения "Wrong loader, giving up...".Выяснение объема памяти системы. Для этого используется вызов трех различных функций BIOS: E820h, которая позволяет собрать карту памяти, затем E801h, кото- рая вернет 32-битный размер памяти и последней вызывается 88h, которая вернет размер в диапазоне 0-64 МБ. Полученные значения сохраняются для дальнейшего использования.Настройка режима видеоадаптера. Возможность выбора видеорежима зависит от конфигурации ядра. Можно указать специфичный (предопределенный) режим, кото-
рый будет использован в процессе загрузки ядра, либо запросить меню со списком режимов, из которого пользователь выберет режим по своему желанию.Осуществляется подготовка к переключению в защищенный режим: ядро перемеща- ется в подходящее место (если это необходимо), подправляются адреса и значения регистров.Производится переключение процессора в защищенный режим.
Процесс init и файл /etc/inittab
Если в параметре начальной загрузки "init="не задан запуск какой-то другой программы, после монтирования корневой файловой системы в режиме "только для чтения"ядро запускает процесс init, который является родоначальником всех других процессов в Linux. Сам по себе init ничем не отличается от других программ в системе Linux, просто это первая (и единственная) программа, которая запускается непосредственно ядром, все остальные процессы являются потомками процесса init. Файл программы init вы можете найти в каталоге /sbin среди других исполняемых файлов.Init отвечает за продолжение процедуры загрузки, и перевод системы от начального состояния, возникающего после загрузки ядра, в стандартное состояние обработки запросов многих пользователей. Основная задача, которая стоит перед init, заключается в том, чтобы запускать в определенной последовательности другие программы в процессе загрузки системы и останавливать процессы в случае переключения уровня выполнения (в частности, при остановке системы). Init выполняет еще массу различных операций, необходимых для дальнейшей работы системы: проверку и монтирование файловых систем, запуск различных служб (демонов), запуск процедур логирования, оболочек пользователей на различных терминалах и т.д.Производители различных дистрибутивов имеют свои подходы к стилям загрузки и так называемым "уровням выполнения". Уровни выполнения (run levels) – это просто несколь- ко стандартных вариантов загрузки системы, каждый из которых определяет перечень действий, выполняемых процессом init, и состояние системы после загрузки, т. е. конфигу- рацию запущенных процессов. Уровень выполнения идентифицируется одним символом. В большинстве дистрибутивов ОС Linux используется 6 основных уровней выполнения.В случае Red Hat, распределение уровней будет следующим: 0 остановка системыоднопользовательский режим
многопользовательский режим без NFS (то же, что и 3, если компьютер не работает с сетью)полный многопользовательский режим 4 использование не регламентировано5 запуск системы в графическом режиме 6 перезагрузка системы;
В некоторых дистрибутивах (например, в Debian), кроме того, используется дополнитель- ный уровень S (или s) – примерно то же, что и однопользовательский режим, но S и s используются в основном в скриптах.Как видите, уровни 0, 1 и 6 зарезервированы для особых случаев. Относительно того, как использовать уровни со 2 по 5, единого мнения не существует. Некоторые системные администраторы используют разные уровни для того, чтобы задать разные варианты работы, например, на одном уровне запускается графический режим, на другом работают в сети и т. д.Уровень выполнения может быть задан как одна из опций, передаваемых ядру загрузчиком. Обычно единственной причиной, по которой уровень загрузки может быть задан как аргумент при загрузке, является необходимость запуска системы в однопользовательском режиме (уровень выполнения 1) для выполнения каких-то административных задач или в случае повреждения диска. Но если уровень выполнения не задан как опция загрузки, то init будет загружать систему на уровень, заданный в файле /etc/inittab.Конфигурационный файл /etc/inittab состоит из отдельных строк. Если строка начинается со знака # или пуста, то она игнорируется. Все остальные строки состоят из 4 полей, разделенных двоеточиями:id:runlevels:action:process где:id – идентификатор строки. Это произвольная комбинация, содержащая от 1 до 4 символов. В файле inittab не может быть двух строк с одинаковыми идентификато- рами;runlevels – уровни выполнения, на которых эта строка будет задействована. Уровни задаются цифрами или буквами без разделителей, например, 345;process – процесс, который должен запускаться на указанных уровнях. Другими словами в этом поле указывается имя программы, вызываемой при переходе на указанные уровни выполнения;action – действие.В поле action стоит ключевое слово, которое определяет дополнительные условия выполне- ния команды, заданной полем process. Допустимые значения поля action:respawn – перезапустить процесс в случае завершения его работы;once – выполнить процесс только один раз при переходе на указанный уровень;
wait – процесс будет запущен один раз при переходе на указанный уровень и init будет ожидать завершения работы этого процесса, прежде, чем продолжать работу;sysinit – это ключевое слово обозначает самые первые действия, выполняемые процес- сом init еще до перехода на какой-либо уровень выполнения (поле id игнорируется). Процессы, помеченные этим словом, запускаются до процессов, помеченных словами boot и bootwait;boot – процесс будет запущен на этапе загрузки системы независимо от уровня выполнения;bootwait – процесс будет запущен на этапе загрузки системы независимо от уровня выполнения, и init будет дожидаться его завершения;initdefault – строка, в которой это слово стоит в поле action, определяет уровень выполнения, на который система переходит по умолчанию. Поле process в этой строке игнорируется. Если уровень выполнения, используемый по умолчанию, не задан, то процесс init будет ждать, пока пользователь, запускающий систему, не введет его с консоли;off – игнорировать данный элемент;powerwait – позволяет процессу init остановить систему, когда пропало питание. Использование этого слова предполагает, что имеется источник бесперебойного пи- тания (UPS) и программное обеспечение, которое отслеживает состояние UPS и информирует init о том, что питание отключилось;ctrlaltdel — разрешает init перезагрузить систему, когда пользователь нажимает комбинацию клавиш <Ctrl>+<Alt>+<Del> на клавиатуре.Этот список не является исчерпывающим.
Инициализационный скрипт rc.sysinit
В обычной ситуации одним из первых действий, выполняемых процессом init является запуск на выполнение скрипта rc.sysinit из каталога /etc/rc.d.Очень кратко, перечень действий, выполняемых скриптом rc.sysinit, выглядит примерно так (на примере дистрибутива Mandriva Linux):Задаются начальные значения общесистемных переменных PATH, HOSTNAME, HOSTTYPE и т.д., а также значения нескольких переменных, которые будут исполь- зоваться на дальнейших этапах загрузки.Определяется, используя содержимое файла /etc/sysconfig/network, должна ли данная система подключаться к какой-то локальной сети. В этом файле просто задается значение переменной NETWORKING (да или нет).Аналогичным образом (то есть путем считывания установок из нескольких файлов, размещаемых в каталоге /etc/sysconfig, и задания каких-то значений переменных) задается необходимость использования usb-устройств, уровень безопасности и т.д.Считываются из файла /etc/init.d/functions определения функций, которые будут использоваться скриптами из каталога /etc/init.d на следующих этапах загрузки (а, возможно, и в работающей системе).Монтируются файловые системы /proc (файловая система, используемая в Linux для определения состояния различных процессов) и /sys.Утилита udev вызывается для создания файлов блоковых устройств в каталоге /dev.
Задается системный шрифт.
Содержимое командной строки загрузки ядра записывается в переменную cmdline.
Выдается сообщение с сообщением о загружаемой систем и информацией о возмож- ности продолжения загрузки в интерактивном режиме.Перенастраиваются параметры ядра путем запуска команды sysctl. Эта операция вы- полняется в скрипте rc.sysinit неоднократно по мере изменения каких-то параметров.Восстанавливается системное время и другие временные установки (установку часо- вого пояса и т.д.), ориентируясь на показания датчика времени в BIOS и значения параметров, заданные при инсталляции системы.Загружаются модули, заданные пользователем в /etc/sysconfig/modules/*.modules.
Задается сетевое имя компьютера (host name), используемое в процедурах идентифи- кации, таких как NIS (Network Information Service), NIS+ (улучшенная версия NIS) и так далее.Задаются настройки, необходимые для подключения устройств Firewire, USB, RAID- массивов, менеджера логических томов и шифрования диска. Например, проверяется существует ли /proc/bus/usb и является ли он каталогом. Если этот каталог суще- ствует, но не указан в файле /proc/mounts, то монтируется файловая система типа usbfs.Проверяется корневая файловая система и, в случае отсутствия проблем, она монти- руется в режиме чтения-записи.Задействуется виртуальная память, активизируется и монтируется swap-раздел, ука- занный в файле /etc/fstab.Проверяются другие файловые системы, перечисленные в /etc/fstab.
Монтируются все файловые системы, перечисленные в файле /etc/fstab.
Проверяются квоты на использование дискового пространства.
Идентифицируется и распознается установленное оборудование, конфигурируются устройства Plug’n’Play, активизируются другие устройства, например, звуковая плата.Проверяет состояние специальных дисковых устройств, таких как RAID (Redundant Array of Inexpensive Disks).Загружаются раскладки клавиатуры. Задается клавиша переключения раскладок.
Инициализируется генератор (псевдо)случайных чисел.
Запускается оптимизация жесткого диска (вызовом команды hdparm).
Обновляется ссылка на файл /boot/System.map (чтобы этот файл соответствовал загружаемому ядру).Содержимое кольцевого буфера ядра выгружается в файл /var/log/dmesg.
Производится удаление всех временных файлов, каталогов и переменных, созданных для целей загрузки.Если в командной строке не задан выбор графической оболочки, то для нее задается установка по умолчанию.
Скрипт rc и запуск системных сервисов
Скрипт rc.sysinit выполняет те задачи по начальной настройке системы, которые не зависят от уровня выполнения, а скрипт /etc/rc.d/rc, который запускается следующим, должен уже произвести перевод системы на тот уровень выполнения, который задан в файле inittab (или в командной строке). В файле inittab присутствует отдельная строка для каждого уровня выполнения, и в этих строках вызывается один и тот же скрипт, и строки отличаются только аргументом вызова этого скрипта. Этот аргумент (или параметр) и задает уровень выполнения. Но, прежде чем рассматривать функции, выполняемые скриптом rc, надо сказать несколько слов о каталоге /etc/rc.d. Этот каталог играет важную роль в процессе загрузки, поскольку он содержит основные скрипты (программы на языке командного процессора shell), служащие для организации процесса загрузки.Каталог rc.d содержит следующий набор подкаталогов:
rc0.drc1.drc2.drc3.drc4.drc5.drc6.dinit.dЕсли просмотреть содержимое подкаталогов rcZ.d, то можно увидеть, что в этих подката- логах содержатся не файлы, а только ссылки на файлы скриптов, находящиеся в других каталогах, а именно (за редким исключением), в каталоге /etc/rc.d/init.d. Подкаталог init.d содержит уже не ссылки, а скрипты, управляющие работой для тех служб, которые обычно запускаются в системе (NFS, sendmail, cron, syslog, httpd и т. п.). Различные скрипты из каталога init.d воспринимают различное число опций (или параметров запуска), но все они понимают опции stop, start и restart.Если необходимо остановить или наоборот запустить какую-то из стандартных системных служб, можно сделать это, вызвав соответствующий скрипт, например,
или
В некоторых дистрибутивах существует удобная утилита service, которая позволяет сделать то же самое, не набирая в командной строке полный путь в соответствующему скрипту:
Однако, очевидно, что эта утилита будет корректно работать только в том случае, если скрипт вызова службы находится в стандартном каталоге.
Запуск процессов getty и login
Когда выполнение rc N завершится, init будет выполнять команды, заданные в строках с ключевым словом respawn для заданного уровня выполнения. Программы, запущенные с условием respawn будут повторно запускаться после завершения.Например, в Red Hat для пятого уровня выполнения в файле /etc/inittab обычно прописаны следующие строки:
Первые 6 из этих строк обеспечивают запуск шести виртуальных консолей. Для этого init порождает процессы, именуемые getty-процессами (от "get tty"— получить терминал), и следит за тем, какой из процессов открывает какой терминал. Каждый getty-процесс устанавливает свою группу процессов, используя вызов системной функции setpgrp, откры- вает отдельную терминальную линию и обычно приостанавливается во время выполнения функции open до тех пор, пока машина не получит аппаратную связь с терминалом.Когда функция open возвращает управление, getty-процесс (демон getty) отображает на экране содержимое файла etc/issue и запускает программу login (регистрации в систе- ме), которая требует от пользователей, чтобы они идентифицировали себя указанием регистрационного имени и пароля.Если пользователь не смог успешно зарегистрироваться, программа регистрации через определенный промежуток времени завершается, закрывая открытую терминальную ли- нию, а процесс init порождает для этой линии следующий getty-процесс, открывающий терминал, вместо прекратившего существование (помните - ключевое слово respawn).Последняя строка в приведенном выше примере, обозначенная идентификатором x, задает регистрацию пользователя в графическом режиме. Эта строка работает только на 5-ом уровне выполнения, поскольку другие уровни в Red Hat не предполагают использования графики.
Старт оболочки Bash
Демон getty запустил программу login, которая выводит предложение ввести имя пользова- теля. Получив это имя, login обращается к файлу /etc/passwd за получением необходимых данных об этом пользователе, в частности, о его идентификаторе, идентификаторе группы, домашнем каталоге и о том, какую оболочку для него запускать. Одновременно выводится запрос на ввод пароля пользователя.Когда пользователь введет пароль, программа login считывает его, шифрует и сравнивает результат с тем, что лежит в соответствующей строке файла etc/shadow.Если пользователь ввел правильный пароль, программа login, запускает командный про- цессор (оболочку). Какую именно оболочку запускать (тут возможен довольно широкий выбор), определяется соответствующим полем в файле /etc/passwd.Наиболее часто применяемым вариантом командной оболочки является bash.
Демонстрация работы загрузчика
Основываясь на предыдущем описании, сделаем не большой загрузчик, который должен поместиться в загрузочную область и выдать информацию о себе. В самом простом виде, он будет выглядеть следующим образом.
1 /*2 * mbr . c3 *
Листинг 1: Исходный код простого загрузчика
4 * Created on : Mar 29 , 20155 * Author : sam6 */
7
8 /* XXX the s e must be at top */9 #i nc l ude " code 16 gcc . h"10 asm ( " jmpl $0 , $main\n" ) ;
11
12 #d e f i n e NOINLINE __attribute__ ( ( n o i n l i n e ) )13 #d e f i n e REGPARM __attribute__ ( ( regparm ( 3 ) ) )14 #d e f i n e NORETURN __attribute__ ( ( noreturn ) )
15
16 /* BIOS i n te r r u p t s must be done with i n l i n e assembly */17 void NOINLINE REGPARM p r i n t ( const char * s ) {18 while (* s ) {19 asm __volatile__ ( " i n t $0x10 " : : "a" ( 0 x0E00 | * s ) , "b" ( 7 ) );20 s++;21 }22 }23 /* and f o r e ve rythi ng e l s e you can use C! Be i t t r a v e r s i n g the f i l e s y s te m , or v e r i f y i n g the k e rne l image e tc . */
24
25<