При включении ЭВМ, в общем случае, ее память не содержит какой либо полезной информации. Это касается и большой универсальной ЭВМ, и персонального компьютера, и микроконтроллера, и т.д. Да, существуют типы памяти, которые сохраняют информацию при отключении питающего напряжения, например,
Но это не решает проблему полностью и окончательно.
Тема статьи возникла, можно сказать, случайно. На основе комментариев и дискуссии к статье
Там мы разобрались, но вопрос на самом деле не так прост, как кажется на первый взгляд, и довольно интересен, в том числе, в историческом аспекте.
Как вы помните, статьи из серии "как работает ЭВМ" являются больше информационно-обзорными.
Суть проблемы
Итак, как я уже сказал, после включения питания ЭВМ ничего не знает и ничего не умеет. Казалось бы, никакой проблемы нет, достаточно загрузить с диска ОС. Но задумайтесь на тем, что для загрузки программы тоже нужна программа, а память ЭВМ все еще пуста.
Я уже слышу возмущенные крики читателей "а как же ПЗУ?"... Да, вы правы, но все ли так просто? Во первых, внешние устройства, с которых может быть загружена ОС, могут быть разными. И совершенно не обязательно, что все эти устройства существуют в момент производства ЭВМ. Во вторых, ОС тоже могут быть разными. Да и постоянно выходят и новые версии уже существующих ОС, и появляются новые ОС. Да и сама ОС не обязательна для работы ЭВМ, может ведь существовать и программа работающая без ОС.
В третьих, файловые системы на тех же дисках могут быть разными и нужно как то найти, где располагается образ ОС, например. В четвертых, нельзя забывать и о загрузке по сети. Как видите, все не так просто, как может показаться обычному пользователю ПК.
Загрузка программы в память ЭВМ при ее включении, или после сброса, называется начальной загрузкой. Здесь важно именно "начальная". И ее выполняет специальная программа начальной загрузки, причем она многоступенчатая, как мы скоро увидим.
Русскоязычный термин "Начальный загрузчик" соответствует англоязычному "Boot loader". В былые времена, когда ЭВМ были большими, больше был распространен термин IPL (Initial Program Loader).
Именно начальный загрузчик и будет основным героем сегодняшней статьи.
Какие еще загрузчики бывают?
При работе ОС тоже находится работа для загрузчика. Но теперь это связывающий перемещающий загрузчик, который является частью ОС или одной из ее служебных программ. Именно этот загрузчик выполняет то, что обычные пользователи привыкли называть запуском программ. Для запуска программу нужно загрузить с диска и выполнить еще массу вспомогательных операций.
Связывающий перемещающий загрузчик мы тоже рассмотрим, но уже в следующих статьях.
Знаком термин загрузчик и тем, кто работает с микроконтроллерами. В данном случае он не обязателен и применяется больше для удобства. В том числе, для обновления прошивки в устройстве с микроконтроллером уже у пользователя.
О загрузчиках в мире микроконтроллеров мы тоже поговорим в последующих статьях цикла.
Начальный загрузчик универсальных ЭВМ
В большинстве ЭВМ установлено и доступно памяти меньше, чем максимально возможно. Поэтому часть адресного пространства может быть безболезненно использована для установки ПЗУ, а не ОЗУ.
Почему именно в области старших адресов памяти? Все очень просто. Во первых, физически установленная память обычно располагается именно в младших адресах. Во вторых, здесь обычно располагаются и важные области памяти, например, векторы прерываний.
Может возникнуть вопрос, что делать, если адресное пространство мало и свободных адресов нет? Например, можно использовать идею "теневого" ПЗУ
После включения ЭВМ или сброса бит в регистре управления сброшен. Поэтому в область верхних адресов памяти отображается ПЗУ с загрузчиком. После окончания загрузки ОС устанавливает бит в регистре управления в 1. И с этого момента ПЗУ уходит в тень, а в верхние адреса памяти отображается обычное ОЗУ.
Теперь, когда мы разобрались с расположением загрузчика (точнее, ПЗУ с загрузчиком) в адресном пространстве процессора, можно перейти к рассмотрению, как этот загрузчик работает. И начнем мы с небольшого исторического экскурса.
Давайте окунемся во времена, когда даже алфавитно-цифровые дисплеи были редкостью. Все ЭВМ в те времена имели большие панели управления, которые производили неизгладимое впечатление на неподготовленных.
На переключателях можно было набрать адрес запуска и после нажатия кнопки (переключателя) "Пуск" процессор начинал выполнение программы с этого адреса. В таких ЭВМ в ПЗУ фактически находилось несколько отдельных загрузчиков и требовалось выбрать нужный задав адрес его начала как адрес запуска.
НМД это накопитель на магнитных дисках, НМЛ - на магнитной ленте. Какой либо диалог с оператором отсутствовал. Просто выбранный (как адрес старта) загрузчик получал управление и выполнял свою работу.
Поскольку производитель универсальной ЭВМ не мог знать, что именно будет загружаться (вспомните, что говорилось в начале статьи), размещенный в ПЗУ загрузчик, небольшая специализированная программа, назовем его аппаратным, просто считывал в память некоторый объем информации с внешнего устройства и передавал ему управление. Предполагалось, что в памяти окажется программа, которая уже будет знать, что делать дальше.
Считываемый с внешнего устройства блок информации зависел от собственно устройства. Например, перфолента считывалась до физического конца ленты, а перфокарты до конца колоды. Для магнитных дисков считывалась нулевая дорожка нулевого цилиндра. Для магнитных лент считывался первый блок ленты.
На иллюстрации я показал место размещения считанного информационного блока абстрактно, "где то в памяти". На практике это определялось производителем ЭВМ. Например, IPL мог загружаться в самое начало ОЗУ. Или в самый конец физически установленной памяти. Правила работы аппаратного загрузчика описывались в документации.
После завершения считывания управление просто передавалось загруженной программе. Никаких проверок не выполнялось. На этом работа аппаратного загрузчика заканчивалась. И уже IPL, программный загрузчик, выполнял загрузку собственно ОС или иной программы. Это была его зона ответственности.
Дальнейшая загрузка тоже могла быть многоступенчатой. Например, IPL загружал ядро ОС, которое и занималось загрузкой всех остальных компонентов системы. Это уже не является темой сегодняшней статьи.
Важно понимать, что IPL, с какого бы устройства он не был загружен, дальнейшую загрузку ОС мог выполнять с любого устройства. Например, аппаратный загрузчик считывал IPL с перфоленты, а он уже загружал ОС с диска. Точно так же важно понимать, что не существовало универсального программного загрузчика. IPL жестко связан с тем устройством, с которого он будет загружать ОС. Не с устройством, с которого он сам загружается, а с устройством, с которого будет загружать он.
Немного позже появились диалоговые загрузчики. Теперь не нужно было помнить и набирать адреса отдельных загрузчиков, но суть не сильно изменилась. Теперь нужно было на дисплее набрать, чаще однобуквенную, команду и адрес внешнего устройства, с которого выполняется загрузка, или просто адрес устройства.
Да, на экране дисплея появлялась веселая зеленая надпись, например,
boot>
и мигающий курсор приглашал оператора подсказать, откуда выполнять загрузку. Оператор мог ввести, например,
- L 170 - загрузка к дискового накопителя имеющего адрес 70 (диск 0 УУ 7) в первом селекторном канале
- DP0 - загрузка с накопителя на пакетных магнитных дисках с номером 0
И задание адреса загрузчика с переключателей, и ручной ввод команд требовали определенных знаний, но ведь и операторы тех ЭВМ проходили обучение и были профессионалами.
Не считая диалогового режима взаимодействия с оператором, работа таких начальных загрузчиков ничем не отличалась от ранее рассмотренного.
Появление персональных ЭВМ внесло свою специфику. Ведь теперь пользователь не обязательно был специалистом. В первых ПК начального загрузчика могла не быть вовсе. Выбор программы осуществлял пользователь просто установив соответствующий картридж (ПЗУ). Или память машины делилась на две больших области - системную (ПЗУ) и пользовательскую (ОЗУ).
В системной области размещался простенький прототип ОС, часто называемый программной-монитором и интерпретатор языка программирования высокого уровня. Чаще всего Basic, реже Фокал. Встречался и Форт. написанную пользователем программу на ЯВУ можно было сохранить на обычном бытовом магнитофоне и загрузить снова. Но это выполнялось средствами собственно интерпретатора.
При этом в состав программы-монитора входил и загрузчик, позволяющий загружать с ленты и двоичные программы. Этот загрузчик имеет некоторое сходство с начальным, но предназначен для другого. Он просто считывает двоичную информацию с ленты и размещает ее начиная с заданного адреса.
Появление и развитие IBM-PC потребовало сделать процедуру начальной загрузки еще более простой для обычного пользователя. Да, некоторые первые IBM-PC тоже имели ПЗУ с встроенным интерпретатором Basic. Но все таки это были уже далеко не игрушечные 8-битные машины. И для этих машин требовался именно полноценный начальный загрузчик.
Поскольку сначала из внешних носителей были только дискеты, загрузчик не был сложным и многофункциональным. Но он уже проверял, что именно загружается. Проверка сводилась к простой двухбайтной сигнатуре. Если ее не было, на экран выдавалось сообщение, что носитель не содержит загружаемой системы. Никакого другого взаимодействия с пользователем не предусматривалось.
При этом сам процесс загрузки был точно таким же, как мы ранее рассматривали. В ОЗУ считывался "загрузочный сектор", тот самый IPL, которому и передавалось управление. Сам загрузчик в ПЗУ (по прежнему будем называть его аппаратным) был частью BIOS - базовой системы ввода-вывода. BIOS можно считать просто набором простых и достаточно стандартизованных драйверов, которые могли использовать прикладные программы, что бы не вдаваться в тонкости управления физическими устройствами. Ну и, разумеется, средством конфигурирования (настройки) некоторых параметров ПК.
Чуть позже появились жесткие диски (прозванные в народе винчестерами), самых разных размеров, интерфейсов, параметров. Потом оптические диски, компьютерные сети, USB устройства. Это привело к усложнению аппаратных загрузчиков. Но сама процедура загрузки, по сути, осталась той же самой. Но появилось понятие "последовательность загрузки", очередности перебора внешних накопителей, с которых машина пытается загрузиться. Если не получилось загрузиться с первого устройства, то выполняется попытка загрузки со второго, и так далее.
Если говорить о ПК, то на смену MBR пришла GPT, появилось множество файловых систем, на смену BIOS пришел UEFI. Но сама идея начальной загрузки универсальной ЭВМ осталась неизменной. Начальный загрузчик собственно машины ничего не знает о загружаемой ОС. Он просто считывает программный загрузчик, который, как предполагается, знает все о загружаемой ОС и передает ему управление.
Заключение
Сегодня мы, очень кратко и упрощенно, начали рассматривать интересную и многогранную тему загрузчиков. К сожалению, состояние здоровья не позволило сделать статью более подробной. Она писалась очень долго и тяжело. Однако, здоровье потихоньку возвращается.
В следующей статье поговорим и связывающем перемещающем загрузчике. Будет интересно!
Приглашаю читателей посетить дружественный канал