Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция4.о.с.docx
Скачиваний:
2
Добавлен:
26.11.2019
Размер:
22.08 Кб
Скачать

ОС Unix. Загрузка и завершение работы

Дальше мы будем обсуждать одно семейство ОС, а именно Unix.

Загрузка Unix.

В прошлой лекции мы рассмотрели запуск ОС на этапе от загрузчика, содержащегося в ПЗУ, до загрузки самой ОС. В случае, когда загружается ОС Unix, говорят, что загружается ядро ОС. Это один файл, который загружается в память и запускается последним загрузчиком. Называться этот файл может как угодно, важно лишь правильно указать на него этому последнему загрузчику. Например, файл ядра может нызываться /unix или /boot/vmlinuz.

Единственное ограничение состоит в том, что файл ядра должен находиться в корневом разделе. Впрочем, ничто (кроме, возможно, размера последнего загрузчика) не мешает брать файл ядра из произвольного места на диске, так что не удивлюсь, если узнаю, что какие-либо загрузчики способны это делать. Единственное, что мне будет при этом непонятно,-- зачем это кому-то может понадобиться.

ОС Unix поставляется с исходным кодом. Это предполагает, в частности, что существует возможность собирать (компилировать) разные версии ядра. Чаще всего, в процессе установки ставится толстое ядро, содержащее все возможные драйверы, с внутренними таблицами (например, таблицей процессов) огромного размера. Поэтому пересборка ядра для конкретного компьютера имеет некоторый смысл. Кроме того, чтобы добавить новый тип устройства (драйвер), надежнее всего систему пересобрать.

Теперь посмотрим, что делает ядро ОС Unix при загрузке.

Самоинициализация

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

Устройства разные системы ищут по-разному. Некоторые опрашивают порты ввода-вывода и подбирают для активных портов драйверы (из имеющихся в ядре или подгружаемых). Другим надо на этапе сборки ядра явно указывать, какие устройства (драйверы) надо инициализировать и даже какие порты опрашивать. Некоторые ОС позволяют драйверы подгружать в ядро в процессе работы системы. В принципе, это было бы небезопасно, если бы драйверы подгружались независимо от наличия устройства, поэтому ядро грузит только те драйверы, которые обслуживают имеющиеся устройства.

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

По аналогичной причине возникает также необходимость в многовариантной загрузке Unix. Пока работоспособность нового ядра не протестирована, необходимо сохранить возможность выбрать загрузку старого, проверенного ядра. Иначе в случае, если новое ядро откажется загружаться, придется систему восстанавливать внешними средствами, а то и переустановкой ОС.

Итак, устройства и драйверы для них обнаружены, память протестирована. Можно создать таблицы для процессора и перевести процессор в защищенный режим, что система и делает.

Инициализация системы в защищенном режиме

Кроме того, что ядро переводит процессор в защищенный режим, необходимо выполнить еще одно важное ритуальное действие. Причина необходимости этого действия в том, как устроено выполнение программ в Unix. Подробнее о выполнении программ расскажу в шестой лекции, а пока только кратко обрисую.

Единицей учета выполняющихся программ является процесс. Каждому процессу назначается уникальный идентификатор (pid). Каждый процесс порождается другим процессом при помощи системного вызова fork (то есть, почкованием, дублированием себя). Соответственно у каждого процесса есть родительский процесс, про который дочерний процесс знает через pid родительского процесса (ppid). Это нужно для упрощения взаимодействия между родительским и дочерним процессами.

Но самый первый процесс создать некому, поэтому его создает ядро. Этот процесс называется init и всегда имеет pid = 1. После запуска этого процесса ядро прекращает выполняться и остается только в виде обработчиков прерываний и системных вызовов. Некоторые части ядра по неизвестным мне причинам тоже оформляются как процессы. Например, таким псевдопроцессом является демон подкачки. Все дальнейшие действия по инициализации выполняет init.