Споры о самом сложном проекте во всем IT будут продолжаться вечно. Некоторые будут говорить что тяжелее всего написать ОС, другие скажут игровой движок, может еще попасться драйвер.
В этой статье я постараюсь подробно расписать свой опыт в написании ОС, работающей на BIOS.
Да что там такого?
Да, сначала может показаться, что нужно написать лишь загрузчик и перейти на C++, и тогда все будет как по маслу. Но такие надежды часто разбиваются либо об загрузчик, либо о невозможности нормальной отладки на ранних этапах.
Чтоб начать писать ОС, нужно смириться с тем, что читабельный контент будет встречаться очень редко. Когда я писал свой первый загрузчик, я часто натыкался на статьи на Хабре, где все прекрасно расписали. Но не все так просто — часто встречаются хорошие статьи, но без продолжения. Например, человек расписал подробно все шаги от настройки инструментов до запуска, но результат был лишь выводом текста на экран.
Такие статьи часто не имеют никакого продолжения, но помогают новичку начать работу. Если в процессе он сдается, значит пока что ОС написать он не сможет. Это не хорошо и не плохо, наверняка он хорош в чем‑то другом.
Что должен делать загрузчик?
Загрузчик ОС представляет из себя крохотный код, который BIOS загружает из первого сектора диска и, если все понимает что это реально загрузчик, передает управление. Сектор диска у BIOS это лишь 512 байт.
При загрузке BIOS проверяет сигнатуру загрузчика, чтоб случайно не передать управление не загрузчику. Он сравнивает два последних байта у этого загрузчика. Если это 0x55 и 0xAA, BIOS передает управление этому коду.
Когда загрузчик получил управление, он либо сразу передает управление на второй этап загрузки, либо перед этим настраивает 32 битный режим. Загрузчик должен быть лишен багов, иначе вся ОС не сможет загрузиться.
Почему это тяжело? 512 байт — очень малый объем. Слишком малый. Каждая инструкция занимает по несколько байт.
Stage2. Что это?
Нет нормальных операционных систем, помещающихся в загрузчик. Именно поэтому загрузчик должен загрузить в оперативную память с диска уже второй этап и передать ему управление.
Второй этап часто называют stage2. Он отвечает за подготовку системы к загрузке уже самого ядра. Его задача заключается в переходе в нужный режим (иногда это 32 битный, но чаще 64 битный), загрузке ядра с диска и настраивает систему. Иногда он позволяет выбрать нужную ОС.
Почему это тяжело? Этот этап все еще на ассемблере. Но его работа гораздо тяжелее загрузчика. Он должен подготовить систему к ядру, которое уже наверняка будет написано на более высокоуровневом языке. Часто ядра написаны на C либо C++, лично я писал его на C++. Если загрузчик уже перешел в защищенный режим, вы не можете использовать BIOS.
Теперь вам нужно работать с компьютером напрямую. Работа осуществляется через порты ввода/вывода. Есть команды inb, inw для ввода; outb, outw для вывода. Вместо прерываний, вы можете только вручную программировать устройства. Именно поэтому часто видео‑режим ставят в загрузчике, чтоб не писать драйвер видеокарты.
Ядро? Что сложного?
На самом деле, ядро может быть и простым. Но простое ядро — лишь вывод небольшого сообщения на экран. Пообщаться с пользователем дается ядру ох как нелегко.
В зависимости от видеорежима, ядро может по разному общаться с пользователем. Либо текстовый буфер, либо графический.
Текстовый режим представляет фреймбуфер, начинается он с адреса 0xB8000, его размер — 4KB. Любой байт, записанный в этот буфер, будет отображен на экран текстом.
Графический режим работает в точности также, но размер буфера уже в тысячи раз больше, и туда пишут не символы, а пиксели. Пиксель — обычно 3 либо 4 байта, может быть как и RGB так и BGR. Ядро должно это тоже предусмотреть, чтобы не показывать инвертированную картинку на экран.
Базовые функции ядра ОС
Ядро ОС должно предоставлять буквально все, что нужно программам и оболочке. Рассмотрим самые базовые функции.
Управление памятью. Выделение/освобождение кусков памяти в куче; Настройка таблиц записей (см. ниже); Защита памяти между процессами.
Управление процессами. Создание/уничтожение процессов; распределение сотен процессов между ядрами процессора (обычно их 4-8).
Возможности для программ. Программы всегда используют возможности ядра. Например, создать файл это тоже обращение к ядру. Вывод в консоль, выделение памяти и так далее — все обращение к ядру.
Диспетчер устройств. Обнаружение устройств; Управление драйверами.
Базовые драйверы. Таймер, клавиатура, мышь, диск, сеть.
Файловая система. Управление диском на уровне секторов, в которых лишь кучка байт. Создание абстракций: файл, папка, символическая ссылка и так далее.
Сеть. Управление дикой сетью. Дичайшей сетью.
Графика и видеокарта. Вот тут начинается реальный ужас (см. ниже).
Все эти функции должны быть хорошо и безошибочно реализованы, иначе либо все ядро, либо пользовательские программы будут постоянно завершаться с ошибкой.
Ожидание VS реальность
Многие знают, что написать ОС тяжело. Но часто не знают насколько это тяжело.
Написание любой функции требует не простого, а правильного подхода, иначе ваш код вам отомстит, и очень жестко. Часто люди спотыкаются на простых решениях, которые потом дают ошибки и UB.
«Напишу ОС и разбогатею» — На самом деле, какой бы хорошей ваша ОС ни была, она никогда не будет массово используемым продуктом. Причины этому довольно просты.
«Моя ОС будет весить лишь несколько мегабайт!» — Это возможно, но ОС будет работать только в тех условиях, в которых она создавалась. Совместимость — главная причина веса существующих ОС.
«Напишу ОС за месяц и забуду» — Не выйдет. Вы затянетесь и не выйдете до нормального результата. А написать нормальную ОС за месяц — невозможно.
«Моя ОС сможет запускать программы для Windows, Linux, MacOS» — Нет, это почти невозможно. Поддержка даже одной системы займет годы кропотливой работы. И всегда будут программы, которые не будут работать в вашей эмуляции. Лучше сосредоточьтесь на своем формате, не подражайте другим.
«Сначала напишу сайт для своего проекта, а потом уже саму ОС» — Вы можете выгореть. Люди от вас будут ждать результатов. Вы потеряете мотивацию и репутацию.
«Напишу все на ассемблере, будет самая быстрая ОС в мире!» — Не спорю, кто‑то из читателей может владеть ассемблером как разработчики ColibriOS, но это будет очень сложно. Для начала напишите ОС на C++ или C, возможно Rust.
Почему Linux и Windows популярны, а ОС которые реально лучше них — нет?
Эти ОС были первыми. Они были нужны, когда единственным вариантом использования компьютера было общение с ним на его «родном» языке, а именно на машинном коде.
Машинный код (исполняемый код) — это даже не ассемблер, это просто байты. Здесь я не буду описывать их, возможно в следующей статье опишу. Процессор исполняет машинный код, в котором описано буквально каждое действие программы. Иногда исполняемый код хранится с отдельной памяти (Гарвардская архитектура), но чаще всего используется архитектура Фона Неймана, где в одной памяти хранится данные и код одновременно.
В сложность работы с видеокартой?
Не просто так я ей уделяю особое внимание.
Видеокарта — монстр параллелизации и оптимизации графических вычислений. У процессора есть несколько ядер, обычно 4-8. У видеокарты — тысячи ядер, просто менее мощных чем у процессора. И всеми ними надо управлять.
Разработка драйвера видеокарты — отдельное счастье. Полноценный драйвер займет от 500К до 2М строк. И это только на одну фирму. У каждой видеокарты разный интерфейс обращения, в отличие от процессора, у которого разные фирмы — примерно одинаковые команды.
Почему? Когда появились видеокарты, люди не успели стандартизировать их. И теперь каждая корпорация диктует программам свои условия, а NVIDIA вообще не разрешает написание драйверов под их видеокарты. Все драйвера они пишут сами.
Заключение
Я начал ОС только потому, что заболел. Делать было нечего, работы у меня не было, с детьми играть не надо было (я в 9 классе, какие дети?). Решил начать писать ОС, просто было скучно. Идет уже 4 месяц написания, собралось небольшое комьюнити (люди из моей школы, 15 человек). Любая программа использует тысячи слоев абстракций и даже не думает, насколько ей хорошо.
Любому программисту, уверенному в своих силах, стоит начать писать ОС. Это незабываемый проект и прекрасное портфолио.
